One of the reasons for using ConcurrentHashMap when looking at Java concurrent containers and frameworks today is: Thread unsafe HashMap. A HashMap can cause an infinite loop when performing a put operation concurrently, because multithreading causes the Entry list of a HashMap to form a circular data structure that can be searched in an infinite loop. Correct the reason to see other blogs, are more abstract, so here in a graphical way to show, hope to support!
(1) When adding elements to HashMap, it will cause the expansion of HashMap container. The principle will not be explained any more, and the source code is directly attached as follows:
(2) refer to the above code, then introduced into the transfer method, (introduction focus) this is HashMap concurrency, will cause the root cause of the loop, the following combined with the source code of transfer, explain the principle of the generation of the loop, first list transfer code (this is JDK7 source so), as follows:
(3) Hypothesis:
Map<Integer> map = new HashMap<Integer>(2); // Only two elements can be placed, where the threshold is 1 (when the table is filled with only one element), that is, when the insert element is 1, the capacity will be expanded (as known from addEntry method) // Two elements 3 and 7 will be placed, and if the insert element 8 (after hash mapping, it is not equal to 1), the capacity will be expandedCopy the code
Suppose the placement result is shown as follows:
Now you have two threads, A and B, both of which perform the PUT operation, that is, add elements to the table, that is, both threads A and B see A snapshot of the state of the diagram above
The execution sequence is as follows:
Execution 1: Thread A suspends at (1) in the Transfer function (marked in the transfer function code). Now we’re on the stack of thread A
Execution 2: Thread B executes the while loop in the Transfer function, that is, it will change the original table into a new table (thread B’s own stack) and then write it into the memory. (Assuming both elements map to the same location under the new hash function)
Execution 3: Thread A disconnects and then executes (seeing the old table) from transfer code (1), currently e = 3, next = 7, as described above.
1. Process element 3 and add element 3 to the new table in thread A’s own stack (the new table is in thread A’s own stack, which is thread private and does not affect thread 2).
Thread A copies element 7, e = 7, and next = 3 because thread B changed its reference
Next = 3; next = null; exit the while loop. After executing the while loop, the contents of the new table are as follows:
4. When the operation is complete, the search is stuck in an infinite loop!