问题描述
我了解的唯一区别是迭代器之间。 SkipList
具有弱一致性,而TreeSet
具有快速失败。除此之外,我没有看到SkipList
内部有任何同步方法(尽管它在并发包中)。
有人SkipList
在没有同步的情况下如何并发?它可以帮助我解决哪些问题?除了迭代器之间的区别之外,为什么还要使用它?
解决方法
„ …当SkipList中没有任何同步时,它如何并发?……”
TL; DR - ConcurrentSkipListSet
是 并发 同时 执行线程无法同时写入其所拥有的元素。它无需使用 synchronized
和锁即可实现其并发性。
长版本
在并发集合的上下文中, 并发并不一定意味着所有这些类都使用监视器( aka,synchronized
关键字)来实现线程安全。
首先,您应该了解线程安全本质上是确保两个或多个竞争线程不会修改应用程序的共享状态。然后,您意识到除了 synchronized
之外,还有其他方法(性能更高)来实现线程安全。
首先确保您的状态不能被修改(它是不可变的)是获得线程安全的一种简单但非常有效的方法。
此外,可以通过将其线程安全职责委派给另一个线程安全的类,从而使该类具有线程安全性。
ConcurrentSkipListSet
被认为是 并发 ,因为正如Javadoc所说,它是:“ Insertion,removal,update,and access operations safely execute concurrently by multiple threads”
它实现{em> concurrency ,因为它delegates its thread safety responsibilities to a thread-safe class;即: {ConcurrentSkipListMap
。
ConcurrentSkipListSet
是线程安全的,因为 ConcurrentSkipListMap
是。而且 ConcurrentSkipListMap
是线程安全的,因为在内部使用AbstractMap.SimpleImmutableEntry<K,V>
可以保证其任何状态(其键和值)都不能由当前正在执行的线程修改,因为其状态为不可变。
您可以在上面链接到的源代码中的多个位置看到 ConcurrentSkipListSet
委托给 ConcurrentSkipListMap
。如果您有兴趣了解有关委托线程安全性的更多信息,建议您阅读Chapter 4,Composing Objects,Java Concurrency In Practice。
„ …有什么问题可以帮助我”
使用它可以获得免费线程安全。与使用 synchronized
相比,这种类型的性能更高-并且脚部射击的风险较小。
„ ...为什么除了迭代器之间的区别之外,我还应该使用它?”
如果您的应用程序状态需要存储在某个集合中,并且可以任何方式访问该集合,以同时执行线程,则使用 { {1}} 是您拥有的线程安全选项。