我想在我的应用程序中使用ConcurrentSkipListMap
,但不太确定如何处理它。查看来源,我没有找到任何synchronized
Lock
收购声明。
Documentation也不太清楚。它说的是操作以原子方式执行。
那么,public K putIfAbsent(K, V)
是非阻塞的吗?
答案 0 :(得分:2)
java.util.concurrent.Concurrent*
API 不幸的是,java.util.concurrent.Concurrent*
类型的Javadoc并不像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不是阻塞,而是“被烧毁”。
答案 1 :(得分:1)
public K putIfAbsent(K, V)
是非阻止的。
ConcurrentSkipListMap
使用CAS。比较和交换(CAS)是一种原子指令。