我想在我的应用程序中使用ConcurrentSkipListMap
,但不太确定如何处理。查看来源,我没有发现任何Lock
获取的synchronized
语句。
文件也不太清楚。它所说的只是操作以原子方式执行。
那么,public K putIfAbsent(K, V)
是非阻塞的吗?
关于java.util.concurrent.Concurrent*
API的说明
不幸的是,java.util.concurrent.Concurrent*
类型的Javadocs在如何实现并发保证方面并不像ConcurrentHashMap
:那样具体
一个哈希表,支持检索的完全并发性和更新的高期望并发性。该类遵循与java.util.Hashtable相同的函数规范,并包括与Hashtable的每个方法对应的方法版本。然而,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表。该类在依赖其线程安全性但不依赖其同步详细信息的程序中与Hashtable完全可互操作。
从本质上讲,多年来,它已经表明,早期的Hashtable
实现在锁定方面非常激进,无法扩展到非常大、非常广泛使用和共享的映射。对于区分读锁和写锁的数据库,需要更高效的方法。
您的具体方法
您的特定方法是"非阻塞"的,因为它不使用监视器来保证一致性和原子性。它依赖于JVM的内存模型对volatile
引用的保证,这在整个实现过程中都会遇到。在这些实现中特别有趣的是,您可以看到这样的循环(在私有doPut()
方法中):
outer: for (;;) {
for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
...
break; // restart if lost race to replace value
因此,竞争线程在同一时间对同一对象进行操作而不会阻塞,但它们可能需要多次尝试才能成功。换句话说,不是阻塞,而是CPU被"烧毁"。
public K putIfAbsent(K, V)
是非阻塞的。ConcurrentSkipListMap
使用CAS。比较交换(CAS)是一种原子指令。