Java ConcurrentHashMap与同步HashMap
在Java ConcurrentHashMap与同步HashMap,java,core,Java,Core,在HashMap上使用包装类SynchronizedMap,与ConcurrentHashMap有什么区别 它只是能够在迭代时修改HashMap(ConcurrentHashMap)?简单回答: 这两个映射都是Map接口的线程安全实现ConcurrentHashMap是为了在需要高并发性的情况下实现更高的吞吐量而实现的 Brian Goetz关于ConcurrentHashMap背后的想法的书读得非常好。强烈推荐。ConcurrentHashMap是线程安全的,无需同步整个映射。当使用锁进行写操
HashMap
上使用包装类SynchronizedMap
,与ConcurrentHashMap
有什么区别
它只是能够在迭代时修改HashMap
(ConcurrentHashMap
)?简单回答:
这两个映射都是Map
接口的线程安全实现ConcurrentHashMap
是为了在需要高并发性的情况下实现更高的吞吐量而实现的
Brian Goetz关于
ConcurrentHashMap
背后的想法的书读得非常好。强烈推荐。ConcurrentHashMap是线程安全的,无需同步整个映射。当使用锁进行写操作时,读取可以非常快地进行。ConcurrentHashMap
使用称为锁剥离的细粒度锁定机制,以允许更大程度的共享访问。因此,它提供了更好的并发性和可伸缩性
另外,为ConcurrentHashMap
返回的迭代器是弱一致的,而不是同步HashMap使用的快速失败技术 SynchronizedHashMap
:
每个方法都使用对象级锁进行同步。因此,synchMap上的get和put方法获得一个锁
锁定整个集合是一项性能开销。当一个线程持有锁时,没有其他线程可以使用该集合
ConcurrentHashMap
是在JDK5中引入的
在对象级别没有锁定,锁定的粒度要细得多。对于ConcurrentHashMap
,锁可能位于hashmap存储桶级别
较低级别锁定的效果是,您可以同时拥有读写器,这对于同步集合是不可能的。这将带来更大的可伸缩性
ConcurrentHashMap
如果一个线程试图修改它,而另一个线程在其上迭代,则不会抛出ConcurrentModificationException
这篇文章读得很好。强烈推荐。同步地图上的方法持有对象上的锁,而在ConcurrentHashMap
中有一个“锁条带化”的概念,即锁被持有在内容的存储桶上。从而提高了可伸缩性和性能 ConcurrentHashMap:
1) 这两个映射都是映射接口的线程安全实现
2) ConcurrentHashMap的实现是为了在需要高并发性的情况下获得更高的吞吐量
3) 对象级别中没有锁定
同步哈希映射:
1) 每个方法都使用对象级锁进行同步 两者都是HashMap的同步版本,其核心功能和内部结构有所不同
ConcurrentHashMap由内部段组成,这些段在概念上可以看作是独立的HashMap。
在高并发执行中,所有这些段都可以由单独的线程锁定。
因此,多个线程可以从ConcurrentHashMap获取/放置键值对,而无需彼此阻塞/等待。
这是为了提高吞吐量而实现的
鉴于
Collections.synchronizedMap(),我们得到了HashMap的一个同步版本,它是以阻塞方式访问的。这意味着,如果多个线程试图同时访问synchronizedMap,则允许它们以同步方式一次获取/放置一个键值对。我们可以通过同时使用ConcurrentHashMap和SynchronizedHashMap来实现线程安全。但是如果你看看他们的架构,就会发现有很多不同
同步hashmap
它将在对象级别保持锁定。因此,如果您想执行任何操作,如put/get,则必须首先获取锁。同时,不允许其他线程执行任何操作。因此,一次只能有一个线程对此进行操作。所以这里的等待时间会增加。与ConcurrentHashMap相比,我们可以说性能相对较低
ConcurrentHashMap
它将在段级别保持锁定。它有16个段,默认情况下将并发级别保持为16。因此,一次可以有16个线程在ConcurrentHashMap上运行。此外,读取操作不需要锁。因此,任意数量的线程都可以对其执行get操作
如果thread1希望在段2中执行put操作,thread2希望在段4上执行put操作,则此处允许。意味着,16个线程一次可以对ConcurrentHashMap执行更新(put/delete)操作
这样这里的等待时间就少了。因此,性能相对优于SynchronizedHashMap
ConcurrentHashMap允许并发访问数据。整个地图分为若干部分
读取操作即get(对象键)
即使在段级别也不同步
但是写入操作,即删除(对象密钥)、获取(对象密钥)
在段级别获取锁。只有整个映射的一部分被锁定,其他线程仍然可以从不同的段读取值,除了锁定的段
同步地图另一方面,在对象级别获取锁。所有线程都应该等待当前线程,而不考虑操作(读/写)。根据java文档
Hashtable和Collections.synchronizedMap(新HashMap())是
同步的。但是ConcurrentHashMap是“并发的”
并发集合是线程安全的,但不受单个排除锁的控制
在ConcurrentHashMap的特殊情况下,它安全地允许
任意数量的并发读取以及可调数量o
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);
}
}
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++;
}
}
}