Are concurrent classes provided by the JDK required to use their instance's own intrinstic lock for synchronization?
The J开发者_开发知识库DK provides a set of thread-safe classes like ConcurrentHashMap, ConcurrentLinkedQueue and AtomicInteger.
Are these classes required to synchronize on this
to implement their thread-safe behavior?
Provided that they do we can implement our own synchronized operations on these objects and mix them with the built-in ones?
In other words is it safe to do:
ConcurrentMap<Integer, Account> accounts
= new ConcurrentHashMap<Integer, Account>();
// Add an account atomically
synchronized(accounts) {
if (!accounts.containsKey(id)) {
Account account = new Account();
accounts.put(id, account);
}
}
And in another thread
// Access the object expecting it to synchronize(this){…} internally
accounts.get(id);
Note that the simple synchronized block above could probably be replaced by putIfAbsent() but I can see other cases where synchronizing on the object could be useful.
Are these classes required to synchronize on this to implement their thread-safe behavior.
No and, not only that, the various code inspection tools will warn you if you do try to use the object lock.
In the case of the put method above, note the javadoc:
A hash table supporting full concurrency of retrievals and adjustable expected concurrency for updates. This class obeys the same functional specification as Hashtable, and includes versions of methods corresponding to each method of Hashtable. However, even though all operations are thread-safe, retrieval operations do not entail locking, and there is not any support for locking the entire table in a way that prevents all access. This class is fully interoperable with Hashtable in programs that rely on its thread safety but not on its synchronization details.
This means that the options are thread safe and there isn't a way to do what you're trying to do above (lock the whole table). Furthermore, for the operations that you use (put and get), neither of them will require such locking.
I particularly like this quote from the javadoc from the values() method:
The view's iterator is a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.
So, if you use this method, you'll get a reasonable list: it will have the data as of the request time and might or might not have any later updates. The assurance that you won't have to worry about the ConcurrentModificationExceptions is a huge one: you can write simple code without the synchronized block that you show above and know that things will just work.
精彩评论