我理解的唯一区别是迭代器之间的区别。 SkipList
具有弱一致性,而TreeSet
具有快速失败。除此之外,我在 SkipList
中没有看到任何同步方法(尽管它位于 Concurrent 包中)。
有人可以向我解释一下 SkipList
在没有任何同步的情况下如何并发吗?它可以帮助我解决哪些问题?除了迭代器之间的差异之外,为什么我应该使用它?
最佳答案
„…how is SkipList concurrent when it doesn't have any synchronization in it?…“
TL;DR - ConcurrentSkipListSet
是并发,因为它保存的元素不能由并发执行线程同时写入。它在不使用 synchronized
和锁的情况下实现了并发。
长版本
并发在并发集合的上下文中,并不一定意味着这些类都使用监视器(又名,synchronized
关键字)实现线程安全。
首先,您应该了解线程安全本质上是确保两个或多个竞争线程不会修改应用程序的共享状态。然后您意识到除了 synchronized
之外,还有其他方法(一些性能更高)来实现线程安全。
首先确保您的状态不能被修改(它是不可变的)是获得线程安全的一种简单但非常有效的方法。
此外,通过将类的线程安全职责委托(delegate)给不同的线程安全类,类可以实现线程安全。
ConcurrentSkipListSet
被认为是并发,因为正如其 Javadoc 所说,它:“Insertion, removal, update, and access operations safely execute concurrently by multiple threads “。
它实现了它的并发性,因为它是 delegates its thread safety responsibilities to a thread-safe class ;即:ConcurrentSkipListMap
。
ConcurrentSkipListSet
是线程安全的,因为 ConcurrentSkipListMap
是线程安全的。 ConcurrentSkipListMap
是线程安全的,因为通过在内部使用 AbstractMap.SimpleImmutableEntry<K,V>
,它保证其状态(其键和值)不能被当前正在执行的线程修改,因为它的状态是不可变的。
您可以在我上面链接的源代码中的多个位置看到 ConcurrentSkipListSet
委托(delegate)给 ConcurrentSkipListMap
。如果您有兴趣了解有关委托(delegate)线程安全的更多信息,我建议您阅读 Chapter 4, Composing Objects, Java Concurrency In Practice 。
„…What problems can it help me with“
使用它可以让你自由线程安全。与使用 synchronized
相比,这种类型的性能更高,而且搬起石头砸自己脚的风险也更小。
„…why should I ever use it other than this difference between Iterators?“
如果您的应用程序的状态需要存储在某个集合中,并且可以以任何方式访问该集合以并发执行线程,则使用 ConcurrentSkipListSet
是您拥有的线程安全选项。
关于java - ConcurrentSkipListSet内部工作原理,与TreeSet的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63541301/