There are two ways to make the HashMap thread safe

Hashmaps are not thread-safe and often require some way to circumvent them when writing programs. The JDK natively provides two ways to make HashMap thread-safe. Method one: through Collections. SynchronizedMap () returns a new Map, the new Map is thread-safe. This requires you to get used to interface-based programming, because what is returned is not a HashMap, but an implementation of a Map. Method 2: rewrite the HashMap, specific can see Java. Util. Concurrent. ConcurrentHashMap. This method is a great improvement over method 1.

The following is an analysis and comparison of the two implementation methods from various angles. How to obtain/release the advantages and disadvantages of locks

1) implementation principles have a principle: by means of the Collections, synchronizedMap () to encapsulate all unsafe HashMap method, even the toString, hashCode are encapsulated. The key points of encapsulation are 1) the use of classic synchronized for mutual exclusion, and 2) the use of proxy mode to create a new class that also implements the Map interface.

[Java] Plain text view copy code? private static class SynchronizedMap

implements Map

, Serializable {// Use serialVersionUID from JDK 1.2.2 for interoperability private static final long serialVersionUID = 1978198479659022715L; private final Map

m; // Backing Map final Object mutex; // Object on which to synchronize SynchronizedMap(Map

m) { if (m==null) throw new NullPointerException(); this.m = m; mutex = this; } SynchronizedMap(Map

m, Object mutex) { this.m = m; this.mutex = mutex; } public int size() { synchronized(mutex) {return m.size(); / /}}
,v>
,v>
,v>
,v>
,v>




*












*






















Principle 2: HashMap is rewritten, with the following major changes. A new locking mechanism (known as optimistic locking) was used. The HashMap has been split into separate blocks, which reduces the possibility of lock collisions in the case of high concurrency.

[Java] Plain text view copy code? public V put(K key, V value) { if (value == null) throw new NullPointerException(); int hash = hash(key.hashCode()); return segmentFor(hash).put(key, hash, value, false); }

2) Different methods of locking mechanism 1: Synchronized method is used, which is a pessimistic lock. You need to acquire the lock before entering, make sure the current object is exclusive, and then modify/read accordingly. Method 2: Optimistic lock is used, only when the object needs to be modified, and the previous value is not modified, if modified by another thread, then return failure. The lock is implemented using NonfairSync. This feature ensures atomicity, mutual exclusion, and cannot be addressed at the JDK level, where the JDK calls the JNI method, which in turn calls the CAS directive to ensure atomicity and mutual exclusion. You can Google JAVA CAS to learn more. How JAVA’s optimistic locking is implemented. If multiple threads happen to operate on the same segment as ConcurrentHashMap, then only one thread will be executed and the others will be locksupport.park (). After execution, one thread will be automatically selected to execute locksupport.unpark ().

[Java] Plain text view copy code? V put(K key, int hash, V value, boolean onlyIfAbsent) { lock(); try { int c = count; if (c++ > threshold) // ensure capacity rehash(); HashEntry

[] tab = table; int index = hash & (tab.length – 1); HashEntry

first = tab[index]; HashEntry

e = first; while (e ! = null && (e.hash ! = hash || ! key.equals(e.key))) e = e.next; V oldValue; if (e ! = null) { oldValue = e.value; if (! onlyIfAbsent) e.value = value; } else { oldValue = null; ++modCount; tab[index] = new HashEntry

(key, hash, first, value); count = c; // write-volatile } return oldValue; } finally { unlock(); }}
,v>
,v>
,v>
,v>

Synchronized locks objects (not classes) on a Hashmap, so the first thread that acquires the lock will block and wait to wake up. Method 2: check AbstractQueuedSynchronizer state, if is 0, then get the lock, or the applicant has been lock, also can again get the lock, and also add 1 state. Lock release: both are the inverse operation to get the lock, and use correctly, two methods are automatically select a thread in the queue to get the lock can obtain CPU resources.

Method 1: Advantages: code implementation is very simple, a look to understand. Disadvantages: From a locking perspective, method 1 directly uses the locking method, which basically locks the largest block of code possible. Performance will be poor.

Method 2: Advantages: Fewer code segments need to be mutually exclusive, resulting in better performance. ConcurrentHashMap Splits the entire Map into multiple blocks, reducing the probability of lock collisions and improving the performance. Disadvantages: The code implementation is slightly more complex.