Thinking logic of computer programs (74) and thinking 74

Source: Internet
Author: User
Tags concurrentmodificationexception

Thinking logic of computer programs (74) and thinking 74

This section describes a commonly used concurrent container-ConcurrentHashMap, which is a concurrent version of HashMap. Compared with HashMap, it has the following features:

  • Concurrency Security
  • Directly supports atomic composite operations
  • Supports high concurrency, fully parallel read operations, and parallel write operations to a certain extent.
  • Compared with the synchronization container Collections. synchronizedMap, the iteration does not need to be locked and ConcurrentModificationException is not thrown.
  • Weak Consistency

Let's take a look at it separately.

Concurrency Security

We know that HashMap is not concurrent and secure. In the case of concurrent updates, the chain table structure of HashMap may form a ring, resulting in an endless loop that occupies the CPU. Let's look at an example:

public static void unsafeConcurrentUpdate() {    final Map<Integer, Integer> map = new HashMap<>();    for (int i = 0; i < 100; i++) {        Thread t = new Thread() {            Random rnd = new Random();            @Override            public void run() {                for (int i = 0; i < 100; i++) {                    map.put(rnd.nextInt(), 1);                }            }        };        t.start();    }}    

Run the above Code. On my machine, an endless loop occurs every time, occupying the CPU.

Why is an endless loop? When multiple threads expand the hash table at the same time, instead of updating a linked list at the same time, the update may be lost, but the process is complex, we will not explain this. Interested readers can refer to this article at http://coolshell.cn/articles/9606.html.

Use the Collections. synchronizedMap method to generate a synchronization container. To avoid this problem, replace the first line of code:

final Map<Integer, Integer> map = Collections.synchronizedMap(new HashMap<Integer, Integer>());

In Java, HashMap also has a synchronized version of Hashtable, which is basically the same as the Map generated using synchronizedMap. We will not repeat it here if synchronized is added to each method call.

Synchronization containers have several problems:

  • Each method needs to be synchronized, and the supported concurrency is relatively low.
  • For iterative and composite operations, the caller needs to lock them, which is troublesome to use and easy to forget.

ConcurrentHashMap does not have these problems. It also implements the Map interface and is implemented based on the hash table. The above code replaces the first line:

final Map<Integer, Integer> map = new ConcurrentHashMap<>();

Atomic compound operation

In addition to the Map interface, ConcurrentHashMap also implements an interface ConcurrentMap, which defines some conditional update operations, specifically defined:

Public interface ConcurrentMap <K, V> extends Map <K, V> {// condition update. If no key exists in the Map, set the key to value and return the value corresponding to the original key, if no, null V putIfAbsent (K key, V value) is returned. // The condition is deleted. If the Map contains a key and the corresponding value is value, it is deleted. If yes, returns true; otherwise, false boolean remove (Object key, Object value); // conditional replacement. If the Map contains a key and the corresponding value is oldValue, replace it with newValue, if yes, true is returned. Otherwise, false boolean replace (K key, V oldValue, V newValue); // condition replacement. If there is a key in Map, value is replaced, returns the value corresponding to the original key. If not, null V replace (K key, V value) is returned );}

If synchronous containers are used, the caller must lock them, while ConcurrentMap implements them as atomic operations. In fact, with ConcurrentMap, the caller cannot lock it either. It does not expose the lock interface or use synchronized.

High concurrency

ConcurrentHashMap is designed for high concurrency. How does it work? The specific implementation is complicated. We will briefly introduce its ideas, mainly including:

  • Segment lock
  • No lock required for read

Synchronous containers use synchronized. All methods compete for the same lock. ConcurrentHashMap uses the segmentation lock technology to divide data into multiple segments, and each segment has an independent lock, each segment is equivalent to an independent hash table, and the segmentation is based on the hash value. Whether it is to save the key-value pair or to search by the key, it is first mapped to the segment based on the key hash value, then, perform operations on the hash table corresponding to the segment.

The use of segment locks can greatly improve the concurrency and allow concurrent read/write between multiple segments. By default, there are 16 segments. However, you can set this number by using the constructor, as shown below:

public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel)

ConcurrencyLevel indicates the estimated number of concurrently updated threads. ConcurrentHashMap converts the number to the integer power of 2, for example, 14 to 16, 25 to 32.

When reading and writing data in each segment, ConcurrentHashMap does not simply use locks for synchronization. CAS is used internally, and atomic writing is used for some writes, we will not introduce it. The implementation effect is that for write operations, the locks need to be obtained and cannot be parallel, but read operations can be performed. Multiple reads can be parallel, while writing can also be read, this makes the concurrency of ConcurrentHashMap much greater than that of the synchronization container.

Iteration

We have introduced in section 66 that the synchronization container requires a lock during iteration, otherwise ConcurrentModificationException may be thrown. ConcurrentHashMap does not solve this problem. After the iterator is created, if another thread modifies the container during the iteration, the iteration continues without throwing an exception.

The problem is, does iteration reflect the changes made by other threads? Or, like CopyOnWriteArrayList introduced in the previous section, does it reflect the copy at the time of creation? The answer is, none of them! Let's look at an example:

Public class ConcurrentHashMapIteratorDemo {public static void test () {final ConcurrentHashMap <String, String> map = new ConcurrentHashMap <> (); map. put ("a", "abstract"); map. put ("B", "basic"); Thread t1 = new Thread () {@ Override public void run () {for (Entry <String, String> entry: map. entrySet () {try {Thread. sleep (1000);} catch (InterruptedException e) {} System. out. println (entry. getKey () + "," + entry. getValue () ;}}; t1.start (); // ensure that Thread t1 starts try {Thread. sleep (100);} catch (InterruptedException e) {} map. put ("c", "call");} public static void main (String [] args) {test ();}}

After t1 is started, an iterator is created. However, before iteration outputs each element, the first sleep for 1 second. After the main thread starts t1, the first sleep to ensure that t1 runs first, then an element is added to map, and the program output is:

a,abstractb,basicc,call

Note: The iterator reflects the latest update, but we changed the add statement:

map.put("g", "call");

You will find that the program output is:

a,abstractb,basic

This shows that the iterator does not reflect the latest update. What is the problem? We need to understand the weak consistency of ConcurrentHashMap.

Weak Consistency

After the ConcurrentHashMap iterator is created, each element is traversed according to the hash table structure. However, the internal elements may change during the traversal process, the iterator does not reflect the changes. If the changes occur in the untraversed part, the iterator will discover and reflect the changes. This is weak consistency.

Similarly, another method of ConcurrentHashMap will appear:

// Add key-value pairs in m to the current Mappublic void putAll (Map <? Extends K ,? Extends V> m)

This method is not an atomic operation. Instead, it calls the put Method to add elements one by one. When the method does not end, some modifications will be reflected.

Summary

This section describes ConcurrentHashMap, which is a HashMap of the concurrent version. It achieves high concurrency through the segment lock and other technologies, supports atomic conditional update operations, and does not throw ConcurrentModificationException, achieving weak consistency.

Java does not have a concurrent version of HashSet, but you can use the Collections. newSetFromMap method to build a ConcurrentHashMap.

We know that HashMap/HashSet is based on hash and cannot sort elements. The corresponding sortable container class is TreeMap/TreeSet. The corresponding versions in the sent package are not based on the tree, it is based on the Skip List (Skip table). The classes are ConcurrentSkipListMap and ConcurrentSkipListSet. What are they?

(As in other sections, all the code in this section is in the https://github.com/swiftma/program-logic)

----------------

For more information, see the latest article. Please pay attention to the Public Account "lauma says programming" (scan the QR code below), from entry to advanced, ma and you explore the essence of Java programming and computer technology. Retain All copyrights with original intent.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.