HashMap problems that may occur in a concurrent environment:
1, multi-threaded put may cause the Get infinite loop, the specific performance of CPU utilization 100%;
Cause: When put element to HashMap, will check hashmap capacity is enough, if not enough, will create a new twice times larger than the original hash table, and then transfer the array from the old hash table to the new hash table, the process of migration is a rehash () process, It is possible for multiple threads to operate at the same time to form a circular list, so when you use Get (), a infinite loop occurs.
// tranfer()片段// 这是在resize()中调用的方法,resize()就是HashMap扩容的方法 for (int0; j < src.length; j++) { Entry e = src[j]; ifnull) { null; do { Entry next = e.next; //假设线程1停留在这里就挂起了,线程2登场 intindexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; whilenull); }}
Line Cheng: Thread1 influence Key1
Thread Two: Thread1 influence Key2
Because of the impact of two threads, there is a cyclical situation
The test code for the problem occurred:
import Java.util.HashMap;import Java.util.concurrent.atomic.AtomicInteger; Public classMyThreadextendsThread {/*** The static variables of the class are shared by each instance, so the concurrent execution of this thread has been manipulating both variables* Select Atomicinteger to avoid possible int++ concurrency problems */ Private StaticAtomicinteger ai =NewAtomicinteger (0);//Initialize a table-length hash table of 1 Private StaticHashmap<integer, integer> map =NewHashmap<integer, Integer> (1);//If Concurrenthashmap is used, no similar problem occurs//private static Concurrenthashmap<integer, integer> map = new Concurrenthashmap<integer, integer> ( 1); Public void Run() { while(AI.Get() <100000) {//continuous self-incrementMap.put(AI.Get(), Ai.Get()); Ai.Incrementandget(); } System. out.println(Thread.CurrentThread().GetName() +"Thread is about to end"); } Public Static void Main(string[] args) {MyThread T0 =New MyThread(); MyThread T1 =New MyThread(); MyThread t2 =New MyThread(); MyThread t3 =New MyThread(); MyThread T4 =New MyThread(); MyThread T5 =New MyThread(); MyThread T6 =New MyThread(); MyThread T7 =New MyThread(); MyThread T8 =New MyThread(); MyThread T9 =New MyThread(); T0.Start(); T1.Start(); T2.Start(); T3.Start(); T4.Start(); T5.Start(); T6.Start(); T7.Start(); T8.Start(); T9.Start(); }}
2, multi-threaded put can cause element loss
Cause: When multiple threads execute addentry (Hash,key, value,i) at the same time, if a hash collision occurs, causing two threads to get the same bucketindex to store, there may be a case where the element overwrite is lost
voidaddEntry(intint bucketIndex) { //多个线程操作数组的同一个位置 Entry<K,V> e = table[bucketIndex]; new Entry<K,V>(hash, key, value, e); if (size++ >= threshold) resize(2 * table.length); }
Suggestions:
Using the Hashtable class, Hashtable is thread-safe;
The use of Java.util.concurrent.concurrenthashmap,concurrenthashmap under concurrent packages enables more advanced thread safety;
or use the Synchronizedmap () synchronization method to wrap HashMap object, get a thread-safe map, and manipulate it on this map.
HashMap in high concurrency if there is no handling of thread safety, what is the security implications, the specific performance of what