2018年8月2日木曜日

Using Java’s Concurrent HashMap with Lambda Expressions

Java has useful classes called collections. Of course, other programming languages have similar things. We handle Java case here. Especially, the HashMap class has been practically used extensively. This is a mechanism that you can store and retrieve (key, value) pairs as you know. In recent years, from smartphones to PCs are also becoming multicore, and on that basis, multiple threads are executed in parallel.

In such a multithreaded environment, this HashMap may not be safe to use. In other words, if more than one thread calls methods of the same HashMap object at the same time, conflicts may occur, causing unintended behavior. However, if locking is applied to the entire HashMap object and only one thread operates exclusively, parallelism will degrade and become a problem.

So, there is a Concurrent HashMap class for multithreading. However, even if you use it, it is not always thread-safe. There are several methods in this class that will be thread-safe, so you need to use them properly.

In this article we will consider an example that is as simple as possible. First, I will use Concurrent HashMap, but it will not be thread-safe. The following program stores the key and its corresponding value only if a specific key has not been registered in the HashMap. Three threads execute it in parallel. The key is an integer from 1 to 5, and the value to be stored is 10 times the integer value of the key. Then, even if multiple threads execute them at the same time, storage (put (key, value) ) for one key should only occur once.

ConcurrentHashMap-unsafe example
https://www.dropbox.com/s/truq16oau53k2ub/ConcurrentHashMap_unsafe_fy.txt?dl=0
However, looking at the execution result, there are cases where it does not. In the following example of execution, "put" was executed twice from separate threads for key = 1. That's because there is a problem with the red frame part of the above list. Another thread is supposed to have executed "!map.containskey" while one thread is executing "! map.containsKey" on line 18 and the following "map.put". That is, it depends on multiple threads judging that "key = 1" has not yet been registered.


In order to avoid this, it is necessary to combine together "check whether key is registered" and "storage of key and value by put" to prevent concurrent modification. It is the following program that realized it. The “map.putIfAbsent” on line 18 is the point. This is an atomic (not interrupted) instruction that executes put only if the key is unregistered.

ConcurrentHashMap-safe example
https://www.dropbox.com/s/tn4ii6emtm4alcn/ConcurrentHashMap_safe_fy.txt?dl=0
Look at the execution result. As shown in the figure below, you can see that put is always executed once for one key. The putIfAbsent method returns null as a return value if the key is not registered, and returns the corresponding value if registered.



This is one example of usage of ConcurrentHashMap. We welcome comments from those who have found something in this article, or who have suggestions.

Thanks
FoYo

0 件のコメント:

コメントを投稿