我所理解的唯一区别是迭代器之间的区别。SkipList
具有弱一致性,而TreeSet
具有fail-fast。除此之外,我在SkipList
中没有看到任何同步的方法(尽管它在Concurrent包中(。
有人能向我解释一下SkipList
在没有任何同步的情况下是如何并发的吗?它能帮我解决什么问题?除了迭代程序之间的差异之外,我为什么要使用它?
">…当SkipList中没有任何同步时,它是如何并发的">
TL;DR
--ConcurrentSkipListSet
是并发,因为并发执行线程无法同时写入它所包含的元素。它在不使用synchronized
和锁的情况下实现了并发。
长版本
并发性在并发集合的上下文中,并不一定意味着这些类都使用监视器(又名synchronized
关键字(实现线程安全。
首先,您应该理解线程安全本质上是确保两个或多个竞争线程不会修改应用程序的共享状态。然后您会意识到,除了synchronized
之外,还有其他方法(一些更高性能的(可以实现线程安全。
首先确保你的状态不能被修改(它是不可变的(是获得线程安全的一种简单但非常有效的方法。
此外,通过将其线程安全职责委派给不同的线程安全类,类可以是线程安全的。
ConcurrentSkipListSet
被认为是并发,因为正如其Javadoc所说,其:">插入、删除、更新和访问操作由多个线程安全地并发执行"。
它实现了并发,因为它将其线程安全责任委托给线程安全类;即:ConcurrentSkipListMap
。
ConcurrentSkipListSet
是线程安全的,因为ConcurrentSkipListMap
也是线程安全的。而ConcurrentSkipListMap
则是线程安全,因为通过在内部使用AbstractMap.SimpleImmutableEntry<K,V>
,它保证当前执行的线程无法修改其状态(其键和值(,因为它的状态是不可变的。
您可以在我链接到上面的源代码中的多个位置看到ConcurrentSkipListSet
委派给ConcurrentSkipListMap
。如果您有兴趣了解更多关于委派线程安全的信息,我建议您阅读第4章,编写对象,Java并发实践。
">…它能帮我解决什么问题">
使用它可以获得免费线程安全。与使用synchronized
相比,这种更具表演性的方式——,射中自己脚的风险也更小。
">…除了迭代程序之间的差异之外,我为什么要使用它">
如果应用程序的状态需要存储在某个集合中,并且该集合可以通过任何方式访问以并发执行线程,那么使用ConcurrentSkipListSet
是线程安全的选项。