in reply to Re^2: Design thoughts: iterator invalidation
in thread Design thoughts: iterator invalidation
It's been quite a while since I last worked with it so this is mostly IIRC, but if I am understanding the documentation correctly, methods like keySet essentially return a snapshot of the key set at the time the iterator was created, so I would think that if the hash is resized by another thread the Iterator would iterate over the "old" key set, and only "may" reflect subsequent changes. And while not quite explicitly stated, because of this snapshot idea, I don't think the Iterators would ever return a key twice or omit a key that has not been modified since the creation of the Iterator. As for locking the entire structure, in Java that's pretty easy to accomplish by a synchronized block over some object (such as the hash table itself), and/or by using synchronizedMap from Collections, although of course locking the entire table is not particularly efficient if done often. I think that's some of the reasoning behind the java.util.concurrent classes: provide a data structure that can safely be used by multiple threads, while still providing decent performance - probably the docs for the package say it best:
The "Concurrent" prefix used with some classes in this package is a shorthand indicating several differences from similar "synchronized" classes. For example java.util.Hashtable and Collections.synchronizedMap(new HashMap()) are synchronized. But ConcurrentHashMap is "concurrent". A concurrent collection is thread-safe, but not governed by a single exclusion lock. In the particular case of ConcurrentHashMap, it safely permits any number of concurrent reads as well as a tunable number of concurrent writes. "Synchronized" classes can be useful when you need to prevent all access to a collection via a single lock, at the expense of poorer scalability. In other cases in which multiple threads are expected to access a common collection, "concurrent" versions are normally preferable. And unsynchronized collections are preferable when either collections are unshared, or are accessible only when holding other locks.
Most concurrent Collection implementations (including most Queues) also differ from the usual java.util conventions in that their Iterators provide weakly consistent rather than fast-fail traversal. A weakly consistent iterator is thread-safe, but does not necessarily freeze the collection while iterating, so it may (or may not) reflect any updates since the iterator was created.
So I think it's a question of the requirements: If changes to the data set need to be seen immediately by all threads, some central lock is probably necessary, but if not, then an interface like this one might be a solution.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^4: Design thoughts: iterator invalidation
by BrowserUk (Patriarch) on Feb 23, 2015 at 18:00 UTC |