Java ConcurrentSkipListMap put方法是线程安全的吗?

Java ConcurrentSkipListMap put方法是线程安全的吗?,java,multithreading,thread-safety,concurrentskiplistmap,Java,Multithreading,Thread Safety,Concurrentskiplistmap,最近,在探索ConcurrentSkipListMap时,我检查了它的实现,发现它的put方法不是线程安全的。它在内部调用doPut,实际添加该项。但是我发现这个方法没有使用任何类似于ConcurrentHashMap的锁 因此,我想知道add是否是线程安全的。看看这个方法,它似乎不是线程安全的——也就是说,如果这个方法由两个线程同时执行,那么可能会出现问题 我知道ConcurrentSkipListMap在内部使用skiplist数据结构,但我希望add方法是线程安全的。我理解错了什么吗?Co

最近,在探索ConcurrentSkipListMap时,我检查了它的实现,发现它的put方法不是线程安全的。它在内部调用
doPut
,实际添加该项。但是我发现这个方法没有使用任何类似于
ConcurrentHashMap
的锁

因此,我想知道
add
是否是线程安全的。看看这个方法,它似乎不是线程安全的——也就是说,如果这个方法由两个线程同时执行,那么可能会出现问题


我知道
ConcurrentSkipListMap
在内部使用skiplist数据结构,但我希望
add
方法是线程安全的。我理解错了什么吗?ConcurrentSkipListMap是否真的不是线程安全的?

我们应该信任Java API。这就是java.util.concurrent package docs所说的:

并发集合


除了队列之外,此包还提供了为在多线程上下文中使用而设计的集合实现:ConcurrentHashMap、
ConcurrentSkipListMap
、ConcurrentSkipListSet、CopyOnWriteArrayList和CopyOnWriteArraySet

我们应该相信javaapi。这就是java.util.concurrent package docs所说的:

并发集合


除了队列之外,此包还提供了为在多线程上下文中使用而设计的集合实现:ConcurrentHashMap、
ConcurrentSkipListMap
、ConcurrentSkipListSet、CopyOnWriteArrayList和CopyOnWriteArraySet

仅仅因为它没有使用
并不会使其线程不安全。该结构可以实现

你应该仔细阅读这本书

。。。插入、删除、更新和访问操作由多个线程同时安全执行。迭代器是弱一致的,返回的元素反映了迭代器创建时或创建之后某个点的映射状态。它们不会抛出ConcurrentModificationException,,并且可以与其他操作同时进行


仅仅因为它没有使用
,并不意味着它的线程不安全。该结构可以实现

你应该仔细阅读这本书

。。。插入、删除、更新和访问操作由多个线程同时安全执行。迭代器是弱一致的,返回的元素反映了迭代器创建时或创建之后某个点的映射状态。它们不会抛出ConcurrentModificationException,,并且可以与其他操作同时进行


实施中的评论说:

考虑到树状索引节点的使用,您可能想知道这是为什么 不使用某种搜索树,这将支持 更快的搜索操作。原因是没有 用于搜索的已知高效无锁插入和删除算法 树。索引节点的“向下”链接的不变性(与 对于真实树中可变的“左”字段),使用 只有CAS操作

因此,他们使用一些低级编程功能,通过比较和交换操作来更改原子映射。通过这种方式,它们可以确保线程安全,而无需同步访问


您可以在源代码中更详细地阅读它。

实现中的注释说:

考虑到树状索引节点的使用,您可能想知道这是为什么 不使用某种搜索树,这将支持 更快的搜索操作。原因是没有 用于搜索的已知高效无锁插入和删除算法 树。索引节点的“向下”链接的不变性(与 对于真实树中可变的“左”字段),使用 只有CAS操作

因此,他们使用一些低级编程功能,通过比较和交换操作来更改原子映射。通过这种方式,它们可以确保线程安全,而无需同步访问


您可以在源代码中更详细地阅读它。

文档中说它是线程安全的。您有什么具体的相反证据?我已经检查了它的实现,即类文件ConcurrentSkipListMap.java的源代码。正如我提到的,put方法在内部调用doPut方法,它不使用任何类型的锁。您可以检查ConcurrentSkipListMap.java的源代码,使用锁并不是实现线程安全的唯一方法。阅读
ConcurrentLinkedQueue
,它不使用锁,但完全是线程安全的。您应该阅读非阻塞并发算法,特别是使用CAS。文档中说它是线程安全的。您有什么具体的相反证据?我已经检查了它的实现,即类文件ConcurrentSkipListMap.java的源代码。正如我提到的,put方法在内部调用doPut方法,它不使用任何类型的锁。您可以检查ConcurrentSkipListMap.java的源代码,使用锁并不是实现线程安全的唯一方法。阅读
ConcurrentLinkedQueue
,它不使用锁,但完全是线程安全的。您应该仔细阅读非阻塞并发算法,特别是使用CAS的算法。@Deepak我必须尊重地表示不同意。你的问题是“它是线程安全的吗?”而不是“不使用锁怎么是线程安全的?”@Deepak我的意思是API说它是线程安全的。至于实现,我可以看到我的JRE使用sun.misc.Unsafe.compareAndSwapObject,这可能是他们不使用的方式locks@Deepak我必须恭敬地表示不同意。你的问题是“它是线程安全的吗?”而不是“不使用锁怎么是线程安全的?”@Deepak我的意思是API说它是线程安全的。至于实现,我可以看到我的JRE使用sun.misc.Unsafe.compareAndSwapObject,这可能就是它们在没有锁的情况下的工作方式