Thread-safe collection-ConcurrentHashMap

Why is the HashMap collection thread unsafe?

① Simultaneous put collision leads to data loss: multiple threads perform put operations at the same time, and the calculated hashcode values ​​are equal, and inserting into the same position causes some data to be overwritten

② Simultaneous put expansion leads to data loss: When multiple threads perform the put operation and find that they need to be expanded at the same time, data loss will also occur

③ Infinite loop leads to 100% CPU

The underlying implementation of ConcurrentHashMap JDK1.7 The
outermost layer of ConcurrentHashMap in Java 7 is multiple segments. The underlying data structure of each segment is similar to the HashMap of JDK 1.7. It is implemented based on an array and a linked list; each segment is independently implemented by ReentrantLock (points Segment reentrant lock), each segment does not affect each other, improving concurrency efficiency; ConcurrentHashMap has 16 segments by default, so it can support up to 16 concurrent thread writes at the same time (operations are distributed on different segments), this The default value can be set to other values ​​during initialization, but once initialized,
Insert picture description here
the underlying implementation of ConcurrentHashMap JDK1.8 cannot be expanded. ConcurrentHashMap in
Java 8 is composed of individual nodes, and the underlying data structure of each node is consistent with The HashMap of JDK 1.8 is similar. It is based on
Insert picture description here
the process of the JDK1.8 putVal method based on an array, a linked list and a red-black tree : judging that the key value is not empty (this should be distinguished from the HashMap. HashMap supports both key and value to be empty. ConcurrentHashMap does not Support) -> Calculate the hash value -> Assign a value according to the type of the corresponding location node, or helpTransfer, or increase the linked list, or add a node to the red-black tree -> Check that the threshold is met and convert it into a red-black tree -> return oldVal

The process of JDK1.8 get method: Calculate the hash value -> find the corresponding position, proceed in different situations -> either directly get the value, or find the value in the red-black tree, or find the value in the linked list -> return the result

JDK1.7 mechanism to ensure thread safety: segment lock is used, that is, ReentrantLock lock is added to each segment

JDK1.8 mechanism to ensure thread safety: CAS mechanism plus synchronized locks are used

Why are the HashMap and ConcurrentHashMap of JDK1.8 converted to a red-black tree if the list node exceeds 8?

Because if there are more than 8 linked list nodes, it will lead to very low query efficiency. After converting to a red-black tree, the complexity will change from the original O(n) to O(logn); the probability of the linked list node exceeding 8 is very small. In general, this situation will occur. The most likely reason is that there is a problem with the hash algorithm. For this situation, there is a mechanism to transform into a red-black tree.

The reason why we didn’t directly use the red-black tree for storage at the beginning is that the address space occupied by each node of the red-black tree is twice that of the linked list. In order to save memory space, the linked list storage is used at the beginning

Note: the key and value of ConcurrentHashMap cannot be empty

Guess you like

Origin blog.csdn.net/can_chen/article/details/108686218