Four techniques for using HashMap thread-safely

In this article, we talk about four techniques for using HashMap thread-safely.

1 method inside: use separate HashMap per thread

As shown in the figure below, after tomcat receives the request, it calls the relevant methods of the controller, service layer Service, and database access layer in sequence.

Each time the service layer method serviceMethod is accessed, a separate HashMap will be created inside the method body, the relevant request parameters will be copied to the HashMap, and then the DAO method will be called to perform database operations.

Each HTTP processing thread has its own instance inside the service layer method body HashMap. In a multi-threaded environment, there is no need to HashMapperform any synchronization operations on.

This is also the most common and safest way we use, and it is the most basic operation of CRUD.

2 Configuration data: initial writing, subsequent reading only

After the system starts, we can load the configuration data into the local cache HashMap. After the configuration information is initialized, there is no need to write it, and only read operations are provided in the future.

The above figure shows a very simple configuration class SimpleConfig, which has a HashMap object configMap inside. The constructor calls the initialization method, and the internal logic of the initialization method is to store the configuration data into a HashMap.

The SimpleConfig class exposes the getConfig method to the outside world. After the main thread initializes the SimpleConfig object, when other threads call the getConfig method, it is thread-safe because there is only reading and no writing operations.

3 Read-write lock: blocking when writing, parallel reading, more reading and less writing scenarios

A read-write lock is a lock divided into two parts: a read lock and a write lock. The read lock allows multiple threads to acquire it at the same time, while the write lock is a mutual exclusion lock.

Its rules are:<strong style="font-size: inherit;line-height: inherit;color: rgb(255, 104, 39);">Reading and reading are not mutually exclusive, reading and writing are mutually exclusive, and writing and writing are mutually exclusive. </strong>, suitable for business scenarios with more reading and less writing.

We generally use ReentrantReadWriteLock, which implements ReadWriteLock. The ReadWriteLock interface is also very simple. It mainly provides two methods internally, returning read lock and write lock respectively.

 public interface ReadWriteLock {
    //获取读锁
    Lock readLock();
    //获取写锁
    Lock writeLock();
}

The use of read-write locks is as follows:

  1. Create a ReentrantReadWriteLock object. When using ReadWriteLock, it is not used directly, but obtains its internal read lock and write lock, and then calls the lock / unlock method respectively;
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
  1. Read shared data;
Lock readLock = readWriteLock.readLock();
readLock.lock();
try {
   // TODO 查询共享数据
} finally {
   readLock.unlock();
}
  1. Write shared data;
Lock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
   // TODO 修改共享数据
} finally {
   writeLock.unlock();
}

The following code shows how to use ReadWriteLock to use HashMap thread-safely:

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockCache {
  
    // 创建一个 HashMap 来存储缓存的数据
    private Map<String, String> map = new HashMap<>();

    // 创建读写锁对象
    private ReadWriteLock rw = new ReentrantReadWriteLock();

    // 放对象方法:向缓存中添加一个键值对
    public void put(String key, String value) {
        // 获取写锁,以确保当前操作是独占的
        rw.writeLock().lock();
        try {
            // 执行写操作,将键值对放入 map
            map.put(key, value);
        } finally {
            // 释放写锁
            rw.writeLock().unlock();
        }
    }

    // 取对象方法:从缓存中获取一个值
    public String get(String key) {
        // 获取读锁,允许并发读操作
        rw.readLock().lock();
        try {
            // 执行读操作,从 map 中获取值
            return map.get(key);
        } finally {
            // 释放读锁
            rw.readLock().unlock();
        }
    }
}

Using read-write locks to operate HashMap is a very classic technique. The message middleware RockeMQ NameServer (name service) saves and queries routing information through this technique.

In addition, read-write locks can operate multiple HashMap. Compared with ConcurrentHashMap, ReadWriteLock can control the granularity of cache objects and has greater flexibility.

4 Collections.synchronizedMap: Locked for both reading and writing

The following code, when we use userMap in multiple threads,

static Map<Long, User> userMap = Collections.synchronizedMap(new HashMap<Long, User>());

Enter the synchronizedMap method:

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
       return new SynchronizedMap<>(m);
}

SynchronizedMap contains an object lock Object mutex internally, which is essentially a wrapper class that re-implements the read and write operations of HashMap. We see that each time it is read or written, the synchronized keyword is used to ensure the thread safety of the operation.

Although the Collections.synchronizedMap technique is very simple to use, we need to understand that it will lock every time it is read and written, and the performance will not be particularly good.

5 Summary

In this article, the author summarizes four thread-safe techniques for using HashMap.

1. Inside the method: Each thread uses a separate HashMap

This is the most commonly used and very reliable method. Each thread creates an instance inside the method body HashMap. In a multi-threaded environment, no HashMapsynchronization operations are required.

2. Configuration data: initial writing, subsequent reading only

When the middleware is started, it will read the configuration file and write the configuration data into the HashMap. After the main thread finishes writing, there will be no more writing operations in the future, and other threads can read it, without causing thread safety issues.

3. Read-write lock: blocking when writing, parallel reading, more reading and less writing scenarios

A read-write lock is a lock divided into two parts: a read lock and a write lock. The read lock allows multiple threads to acquire it at the same time, while the write lock is a mutual exclusion lock.

Its rules are:<strong style="font-size: inherit;line-height: inherit;color: rgb(255, 104, 39);">Reading and reading are not mutually exclusive, reading and writing are mutually exclusive, and writing and writing are mutually exclusive. </strong>, suitable for business scenarios with more reading and less writing.

Using read-write locks to operate HashMap is a very classic technique. The message middleware RockeMQ NameServer (name service) saves and queries routing information through this technique.

4. Collections.synchronizedMap: Locked for both reading and writing

The Collections.synchronizedMap method uses the decorator pattern to provide a thread-safe decorator class SynchronizedMap for the thread-unsafe HashMap.

SynchronizedMap is used to indirectly ensure that the operation of HashMap is thread-safe, and the underlying layer of SynchronizedMap also uses the synchronized keyword to ensure the thread-safety of operations.

The pirated resources of "Celebrating More Than Years 2" were uploaded to npm, causing npmmirror to have to suspend the unpkg service. Microsoft's China AI team collectively packed up and went to the United States, involving hundreds of people. The founder of the first front-end visualization library and Baidu's well-known open source project ECharts - "going to the sea" to support Fish scammers used TeamViewer to transfer 3.98 million! What should remote desktop vendors do? Zhou Hongyi: There is not much time left for Google. It is recommended that all products be open source. A former employee of a well-known open source company broke the news: After being challenged by his subordinates, the technical leader became furious and fired the pregnant female employee. Google showed how to run ChromeOS in an Android virtual machine. Please give me some advice. , what role does time.sleep(6) here play? Microsoft responds to rumors that China's AI team is "packing for the United States" People's Daily Online comments on office software's matryoshka-like charging: Only by actively solving "sets" can we have a future
{{o.name}}
{{m.name}}

Guess you like

Origin my.oschina.net/makemyownlife/blog/11174967