我理解的唯一区别是迭代器之间。SkipList
有弱一致,TreeSet
有快速失败。除此之外,我看不到任何同步方法SkipList
(尽管它在 Concurrent 包中)。
有人可以向我解释SkipList
当它没有任何同步时如何并发?它可以帮助我解决什么问题,除了迭代器之间的差异之外,我为什么还要使用它?
我理解的唯一区别是迭代器之间。SkipList
有弱一致,TreeSet
有快速失败。除此之外,我看不到任何同步方法SkipList
(尽管它在 Concurrent 包中)。
有人可以向我解释SkipList
当它没有任何同步时如何并发?它可以帮助我解决什么问题,除了迭代器之间的差异之外,我为什么还要使用它?
„<em>…how is SkipList concurrent when it doesn't have any synchronization in it?…</em>“</p>
TL;DR — ConcurrentSkipListSet
is concurrent because the elements it holds cannot be written to at the same time by concurrently executing threads. It achieves its concurrency without using synchronized
and locks.
The long version
Concurrency in the context of the concurrent collections, does not necessarily mean those classes all implement thread safety using monitors (aka, the synchronized
keyword).
First you should understand that thread safety is essentially about ensuring that two or more competing threads do not modify the shared state of an application. Then you realize that there are ways (some more performant) other than synchronized
to achieve thread safety.
Making sure your state cannot be modified (that it's immutable) in the first place is one simple but very effective way to get thread safety.
Also, a class can be thread safe by delegating its thread safety responsibilities to a different, thread-safe class.
ConcurrentSkipListSet
is considered to be concurrent because, as its Javadoc says, its: „<a href="https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/ConcurrentSkipListMap.html" rel="nofollow noreferrer">Insertion, removal, update, and access operations safely execute concurrently by multiple threads“.
It achieves its concurrency because it delegates its thread safety responsibilities to a thread-safe class; namely: ConcurrentSkipListMap
.
ConcurrentSkipListSet
is thread-safe because ConcurrentSkipListMap
is. And ConcurrentSkipListMap
is thread-safe because, by using AbstractMap.SimpleImmutableEntry<K,V>
internally, it guarantees that none of its state (its keys and values) can be modified by currently executing threads, because its state is immutable.
You can see ConcurrentSkipListSet
delegating to ConcurrentSkipListMap
at several places in the source code I linked to above. If you're interested in learning more about delegating thread safety, I recommend you read Chapter 4, Composing Objects, Java Concurrency In Practice.
„<em>…What problems can it help me with“</p>
Using it gets you free thread-safety. The kind that is way more performant — and with way less risk of shooting yourself in the foot — than using synchronized
.
„<em>…why should I ever use it other than this difference between Iterators?“</p>
If the state of your application needs to be stored in some collection and that collection will be accessible in any way to concurrently executing threads, then using ConcurrentSkipListSet
is a thread-safe option that you have.