简体   繁体   English

ConcurrentHashMap 与同步 HashMap

[英]ConcurrentHashMap vs Synchronized HashMap

What is the difference between using the wrapper class, SynchronizedMap , on a HashMap and ConcurrentHashMap ?HashMapConcurrentHashMap上使用包装类SynchronizedMap什么区别?

Is it just being able to modify the HashMap while iterating it ( ConcurrentHashMap )?它是否只能在迭代时修改HashMap ( ConcurrentHashMap )?

Synchronized HashMap同步HashMap

  1. Each method is synchronized using an object level lock.每个方法都使用对象级锁进行同步。 So the get and put methods on synchMap acquire a lock.所以synchMap 上的get 和put 方法需要一个锁。

  2. Locking the entire collection is a performance overhead.锁定整个集合是一种性能开销。 While one thread holds on to the lock, no other thread can use the collection.当一个线程持有锁时,没有其他线程可以使用该集合。

ConcurrentHashMap was introduced in JDK 5. ConcurrentHashMap是在 JDK 5 中引入的。

  1. There is no locking at the object level,The locking is at a much finer granularity.没有对象级别的锁定,锁定的粒度要细得多。 For a ConcurrentHashMap , the locks may be at a hashmap bucket level.对于ConcurrentHashMap ,锁定可能处于哈希图存储桶级别。

  2. The effect of lower level locking is that you can have concurrent readers and writers which is not possible for synchronized collections.较低级别锁定的效果是您可以拥有并发的读取器和写入器,这对于同步集合是不可能的。 This leads to much more scalability.这导致更多的可扩展性。

  3. ConcurrentHashMap does not throw a ConcurrentModificationException if one thread tries to modify it while another is iterating over it.如果一个线程试图修改它而另一个正在迭代它,则ConcurrentHashMap不会抛出ConcurrentModificationException

This article Java 7: HashMap vs ConcurrentHashMap is a very good read.这篇文章Java 7: HashMap vs ConcurrentHashMap是一本很好的读物。 Highly recommended.强烈推荐。

The short answer:简短的回答:

Both maps are thread-safe implementations of the Map interface.这两个映射都是Map接口的线程安全实现。 ConcurrentHashMap is implemented for higher throughput in cases where high concurrency is expected. ConcurrentHashMap是为了在需要高并发的情况下实现更高的吞吐量而实现的。

Brian Goetz's article on the idea behind ConcurrentHashMap is a very good read. Brian Goetz 关于ConcurrentHashMap背后的想法的文章非常好读。 Highly recommended.强烈推荐。

ConcurrentHashMap is thread safe without synchronizing the whole map. ConcurrentHashMap是线程安全的,无需同步整个地图。 Reads can happen very fast while write is done with a lock.当使用锁完成写入时,读取可以非常快地发生。

We can achieve thread safety by using both ConcurrentHashMap and synchronisedHashmap.我们可以同时使用 ConcurrentHashMap 和 SynchronisedHashmap 来实现线程安全。 But there is a lot of difference if you look at their architecture.但是如果你看看他们的架构,就会有很多不同。

  1. synchronisedHashmap同步哈希图

It will maintain the lock at the object level.它将在对象级别保持锁定。 So if you want to perform any operation like put/get then you have to acquire the lock first.所以如果你想执行像 put/get 这样的任何操作,那么你必须先获取锁。 At the same time, other threads are not allowed to perform any operation.同时,不允许其他线程执行任何操作。 So at a time, only one thread can operate on this.因此,一次只有一个线程可以对此进行操作。 So the waiting time will increase here.所以这里的等待时间会增加。 We can say that performance is relatively low when you are comparing with ConcurrentHashMap.可以说和 ConcurrentHashMap 相比,性能比较低。

  1. ConcurrentHashMap并发哈希映射

It will maintain the lock at the segment level.它将在段级别保持锁定。 It has 16 segments and maintains the concurrency level as 16 by default.它有 16 个段,并且默认保持并发级别为 16。 So at a time, 16 threads can be able to operate on ConcurrentHashMap.所以一次可以有 16 个线程可以操作 ConcurrentHashMap。 Moreover, read operation doesn't require a lock.而且,读操作不需要锁。 So any number of threads can perform a get operation on it.因此,任意数量的线程都可以对其执行 get 操作。

If thread1 wants to perform put operation in segment 2 and thread2 wants to perform put operation on segment 4 then it is allowed here.如果thread1想在segment 2执行put操作,thread2想在segment 4执行put操作,这里是允许的。 Means, 16 threads can perform update(put/delete) operation on ConcurrentHashMap at a time.意味着,16 个线程可以同时对 ConcurrentHashMap 执行更新(放置/删除)操作。

So that the waiting time will be less here.这样在这里等待的时间就会少一些。 Hence the performance is relatively better than synchronisedHashmap.因此性能相对优于同步哈希图。

Both are synchronized version of HashMap, with difference in their core functionality and their internal structure.两者都是HashMap的同步版本,核心功能和内部结构不同。

ConcurrentHashMap consist of internal segments which can be viewed as independent HashMaps Conceptually. ConcurrentHashMap由内部段组成,从概念上可以将其视为独立的 HashMap。 All such segments can be locked by separate threads in high concurrent executions.所有这些段都可以在高并发执行中由单独的线程锁定。 So, multiple threads can get/put key-value pairs from ConcurrentHashMap without blocking/waiting for each other.因此,多个线程可以从 ConcurrentHashMap 获取/放置键值对,而不会相互阻塞/等待。 This is implemented for higher throughput.这是为了更高的吞吐量而实施的。

whereas然而

Collections.synchronizedMap() , we get a synchronized version of HashMap and it is accessed in blocking manner. Collections.synchronizedMap() ,我们得到 HashMap 的同步版本,它以阻塞方式访问。 This means if multiple threads try to access synchronizedMap at same time, they will be allowed to get/put key-value pairs one at a time in synchronized manner.这意味着如果多个线程尝试同时访问 synchronizedMap,它们将被允许以同步方式一次获取/放置一个键值对。

SynchronizedMap and ConcurrentHashMap are both thread safe class and can be used in multithreaded application, the main difference between them is regarding how they achieve thread safety. SynchronizedMapConcurrentHashMap都是线程安全类,可以在多线程应用中使用,主要区别在于如何实现线程安全。

SynchronizedMap acquires lock on the entire Map instance , while ConcurrentHashMap divides the Map instance into multiple segments and locking is done on those. SynchronizedMap获取对整个 Map 实例的锁,而ConcurrentHashMap将 Map 实例分成多个段并在这些段上进行锁定。

在此处输入图片说明

在此处输入图片说明

ConcurrentHashMap uses finer-grained locking mechanism known as lock stripping to allow greater degree of shared access. ConcurrentHashMap使用称为lock stripping的细粒度锁定机制来允许更大程度的共享访问。 Due to this it provides better concurrency and scalability .因此,它提供了更好的并发性可伸缩性

Also iterators returned for ConcurrentHashMap are weakly consistent instead of fail fast technique used by Synchronized HashMap.此外,为ConcurrentHashMap返回的迭代器是弱一致的,而不是 Synchronized HashMap 使用的快速失败技术

Methods on SynchronizedMap hold the lock on the object, whereas in ConcurrentHashMap there's a concept of "lock striping" where locks are held on buckets of the contents instead. SynchronizedMap上的方法持有对象上的锁,而在ConcurrentHashMap有一个“锁条带”的概念,其中锁被持有在内容的桶上。 Thus improved scalability and performance.从而提高了可扩展性和性能。

ConcurrentHashMap :并发哈希映射:

1)Both maps are thread-safe implementations of the Map interface. 1)两个map都是Map接口的线程安全实现。

2)ConcurrentHashMap is implemented for higher throughput in cases where high concurrency is expected. 2) ConcurrentHashMap 是为了在需要高并发的情况下实现更高的吞吐量。

3) There is no locking in object level. 3) 对象级别没有锁定。

Synchronized Hash Map:同步哈希映射:

1) Each method is synchronized using an object level lock. 1) 每个方法都使用对象级锁进行同步。

ConcurrentHashMap allows concurrent access to data. ConcurrentHashMap允许并发访问数据。 Whole map is divided into segments.整个地图被分成几段。

Read operation ie.读取操作即。 get(Object key) is not synchronized even at segment level.即使在段级别, get(Object key)也不同步。

But write operations ie.但是写操作即。 remove(Object key), get(Object key) acquire lock at segment level. remove(Object key), get(Object key)在段级别获取锁。 Only part of whole map is locked, other threads still can read values from various segments except locked one.只有整个地图的一部分被锁定,其他线程仍然可以从除了锁定的一个段之外的各个段读取值。

SynchronizedMap on the other hand, acquire lock at object level.另一方面, SynchronizedMap在对象级别获取锁。 All threads should wait for current thread irrespective of operation(Read/Write).无论操作(读/写)如何,所有线程都应等待当前线程。

A simple performance test for ConcurrentHashMap vs Synchronized HashMap . ConcurrentHashMap 与 Synchronized HashMap 的简单性能测试 The test flow is calling put in one thread and calling get in three threads on Map concurrently.测试流程是在一个线程中调用put并在Map上的三个线程中同时调用get As @trshiv said, ConcurrentHashMap has higher throughput and speed for whose reading operation without lock.正如@trshiv 所说,ConcurrentHashMap 具有更高的吞吐量和速度,其无锁读取操作。 The result is when operation times is over 10^7 , ConcurrentHashMap is 2x faster than Synchronized HashMap.结果是当操作次数超过10^7 ,ConcurrentHashMap 比 Synchronized HashMap 快2x倍。

Synchronized HashMap同步HashMap

  1. Lock mechanism - It Locks the whole map, so Multiple threads can't access the map concurrently.锁定机制- 它锁定整个地图,因此多个线程无法同时访问地图。 So, performance is relatively less.所以,性能相对较差。

2. Null key or Value - It will allow null as a key or value. 2.空键或值- 允许空作为键或值。

3. Concurrent modification exception - Iterator return by synchronized map throws concurrent modification exception 3.并发修改异常——同步映射返回的迭代器抛出并发修改异常

ConcurrentHashMap并发哈希映射

1. Lock mechanism -Locks the portion, Concurrent hashmap allows concurrent read and write. 1.锁定机制——锁定部分,Concurrent hashmap 允许并发读写。 So performance is relatively better than a synchronized map所以性能相对来说比同步地图好

2. Null key or Value - It doesn't allow null as a key or value. 2.空键或值- 它不允许空作为键或值。 If you use it will throw java.lang.如果你使用它会抛出java.lang。 NullPointerException at Runtime.运行时出现NullPointerException

3. Concurrent modification exception - It doesn't throw concurrent modification exceptions. 3.并发修改异常- 它不会抛出并发修改异常。

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Ex_ConcurrentHashMap {

    public static void main(String[] args) {
        
        Map<String, String> map = new ConcurrentHashMap<>();
        map.put("one", "one");
        map.put("two", "two");
        map.put("three", "three");
        System.out.println("1st  map : "+map);
        String key = null;
        for(Map.Entry<String, String> itr : map.entrySet())
        {
            key = itr.getKey();
            if("three".equals(key))
            {
                map.put("FOUR", "FOUR");
            }
            System.out.println(key+" ::: "+itr.getValue());
        }
        System.out.println("2nd  map : "+map);
        //map.put("FIVE", null);//java.lang.NullPointerException
        map.put(null, "FIVE");//java.lang.NullPointerException
        System.out.println("3rd  map : "+map);
    }
}

在此处输入图片说明

Synchronized HashMap Example同步 HashMap 示例

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

public class Ex_Synchronizedmap {

    public static void main(String[] args) {
        
        Map<String, String> map = new HashMap<>();
        
        map.put("one", "one");
        map.put("two", "two");
        map.put("three", "three");
        map.put("FOUR", null);
        map.put(null, "FIVE");
        
        System.out.println("map : "+map);
        
        Map<String, String> map1 = 
                Collections.synchronizedMap(map);
        System.out.println("map1 : "+map1);
        
        String key = null;
        for(Map.Entry<String, String> itr : map1.entrySet())
        {
            key = itr.getKey();
            if("three".equals(key))
            {
                map1.put("ABC", "ABC");
            }
            System.out.println(key+" ::: "+itr.getValue());
        }
        
        System.out.println("New Map :: "+map1);
        
        
        
        Iterator<Entry<String, String>> iterator = map1.entrySet().iterator();
        int i = 0;
        while(iterator.hasNext())
        {
            if(i == 1)
            {
                map1.put("XYZ", "XYZ");
            }
            Entry<String, String> next = iterator.next();
            System.out.println(next.getKey()+" :: "+next.getValue());
            i++;
        }
    }

}

在此处输入图片说明

As per java doc's根据java doc的

Hashtable and Collections.synchronizedMap(new HashMap()) are synchronized. Hashtable 和 Collections.synchronizedMap(new HashMap()) 是同步的。 But ConcurrentHashMap is "concurrent".但是 ConcurrentHashMap 是“并发的”。

A concurrent collection is thread-safe, but not governed by a single exclusion lock.并发集合是线程安全的,但不受单个排除锁的控制。

In the particular case of ConcurrentHashMap, it safely permits any number of concurrent reads as well as a tunable number of concurrent writes.在 ConcurrentHashMap 的特殊情况下,它安全地允许任意数量的并发读取以及可调整数量的并发写入。 "Synchronized" classes can be useful when you need to prevent all access to a collection via a single lock, at the expense of poorer scalability.当您需要通过单个锁阻止对集合的所有访问时,“同步”类可能很有用,但代价是可扩展性较差。

In other cases in which multiple threads are expected to access a common collection, "concurrent" versions are normally preferable.在期望多个线程访问公共集合的其他情况下,“并发”版本通常更可取。 And unsynchronized collections are preferable when either collections are unshared, or are accessible only when holding other locks.当集合未共享或仅在持有其他锁时才可访问时,最好使用非同步集合。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM