如何在 Java 中同步 HashMap

位置:首页>文章>详情   分类:Java教程   阅读(225)   2023-06-26 07:54:18

Java HashMap 默认是不同步的。如果我们在多个线程正在添加和删除对的并发应用程序中从 HashMap 添加/删除键值对,我们最终可能会出现不一致的映射状态。学习同步 hashmapConcurrentHashMap 在 Java 中。

1、同步HashMap——ConcurrentHashMap

如果我们希望在并发环境中使用 Map,我们的首选应该始终是使用 ConcurrentHashMap 类。 ConcurrentHashMap 通过设计支持并发访问它的键值对。我们不需要执行任何额外的代码修改来启用地图同步。

请注意,从 ConcurrentHashMap 获得的 iterator 不会抛出 ConcurrentModificationException。但是,迭代器被设计为一次只能由一个线程使用。这意味着我们从 ConcurrentHashMap 获得的每个迭代器都设计为由单个线程使用,不应传递。

如果我们这样做,则无法保证一个线程会看到另一个线程对映射所做的更改(无需从映射中获取新的迭代器)。 迭代器保证反映地图在创建时的状态

让我们举一个使用 ConcurrentHashMap 的例子。

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;

public class HashMapExample 
{
    public static void main(String[] args) throws CloneNotSupportedException 
    {
        ConcurrentHashMap<Integer, String> concurrHashMap = new ConcurrentHashMap<>();
        
        //Put require no synchronization
        concurrHashMap.put(1, "A");
        concurrHashMap.put(2, "B");
        
        //Get require no synchronization
        concurrHashMap.get(1);
        
        Iterator<Integer> itr = concurrHashMap.keySet().iterator();
        
        //Using synchronized block is advisable
        synchronized (concurrHashMap) 
        {
            while(itr.hasNext()) {
                System.out.println(concurrHashMap.get(itr.next()));
            }
        }
    }
}

程序输出。

A
B

2.同步HashMap——Collections.synchronizedMap()

Synchronized HashMap 的工作方式也与 ConcurrentHashMap 非常相似,只有很少的区别。

SynchronizedHashMap 一次只允许一个线程执行读/写操作,因为它的所有方法都被声明为同步ConcurrentHashMap 允许多个线程在映射中的不同段上独立工作。这允许在 ConcurrentHashMap 中实现更高程度的并发,从而提高整个应用程序的性能。

来自这两个类的迭代器应该在 synchronized 块中使用,但是来自 SynchronizedHashMap 的迭代器是fail-fast。 ConcurrentHashMap 迭代器不是快速失败的。

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class HashMapExample 
{
    public static void main(String[] args) throws CloneNotSupportedException 
    {
        Map<Integer, String> syncHashMap = Collections.synchronizedMap(new HashMap<>());
        
        //Put require no synchronization
        syncHashMap.put(1, "A");
        syncHashMap.put(2, "B");
        
        //Get require no synchronization
        syncHashMap.get(1);
        
        Iterator<Integer> itr = syncHashMap.keySet().iterator();
        
        //Using synchronized block is advisable
        synchronized (syncHashMap) 
        {
            while(itr.hasNext()) {
                System.out.println(syncHashMap.get(itr.next()));
            }
        }
    }
}

程序输出。

A
B

3.SynchronizedHashMap与ConcurrentHashMap的区别

让我们找出两个版本的地图之间的一些差异,以便我们可以决定在哪种情况下选择哪个版本。

  1. 多个线程可以从 ConcurrentHashMap 添加/删除键值对,而在 SynchronizedHashMap 的情况下只允许一个线程进行更改。这导致 ConcurrentHashMap 的并发度更高。
  2. 无需锁定映射即可读取 ConcurrentHashMap 中的值。检索操作将返回由最近完成的插入操作插入的值。 SynchronizedHashMap 中的读操作也需要锁。
  3. ConcurrentHashMap 不会抛出 ConcurrentModificationException 如果一个线程试图修改它而另一个正在迭代它。迭代器反映了映射在创建时的状态。 SynchronizedHashMap 返回迭代器,它在并发修改时快速失败。

快乐学习!!

阅读更多 :

Java HashMap 指南 HashMap Java 文档 ConcurrentHashMap Java 文档

地址:https://www.cundage.com/article/synchronize-hashmap.html