java线程安全ConcurrentHashMap详解

HashMap在多线程环境下存在线程安全问题,可能导致死循环。线程安全的解决方案包括Hashtable和ConcurrentHashMap。Hashtable由于全局锁导致低效,而ConcurrentHashMap通过分段锁(早期版本)和CAS+锁(JDK 1.8之后)实现高效线程安全。ConcurrentHashMap在JDK 1.8以后采用锁链表头节点和CAS操作,提高了并发性能。
摘要由CSDN通过智能技术生成


前言

众所周知HashMap是非线程安全的,而ConcurrentHashMap是线程安全的,它是目前使用得最多的线程安全map,那么它是如何保证线程安全呢。让我们来一起看一下。


一、HashMap的线程安全问题

在单线程时,HashMap无疑是使用得最多的,哈希算法时间复杂度相对较低,使用高效。但是在多线程的情况下HashMap是非线程安全的。因为在多线程的情况下HashMap的resize()方法容易容易产生环形链表,造成死循环。所以在多线程的情况下,我们需要使用线程安全的map。

二、线程安全的map

1.线程安全的Hashtable

Hashtable是我们最先接触到的线程安全的map,但是在多线程中,因为其效率过低,我们不建议使用。

那么它效率低的原因是为什么呢?

因为Hashtable中对map的操作都使用synchronized上锁了,那么我们每次只能有一个线程对map进行操作
我们看一下Hashtable源码(jdk1.8):

 public synchronized int size() {
   
        return count;
    }
    
 public synchronized boolean isEmpty() {
   
        return count == 0;
    }
   
  public synchronized V put(K key, V value) {
   
        //省略
    }
public synchronized V remove(Object key) {
   
       //省略
    }
//省略

大多数操作的方法都使用了synchronized,而synchronized修饰方法,在一个线程使用该方法时就是锁住了对象,其他线程该对象其他的方法的调用将会被禁止。那么在高并发场景下,多个线程等待一个线程运行完毕是十分影响效率的。所以Hashtable使用较少。

2. ConcurrentHashMap

ConcurrentHashMap也是一种线程安全的map,相对于Hashtable的涉及线程安全的方法都使用synchronized上锁。ConcurrentHashMap的锁就上得更有艺术一些。为了解决一个线程访问方法的低效率问题,ConcurrentHashMap使用了分段锁(jdk1.5)和 synchronized+CAS(jdk1.8)。

分段锁

在jdk1.5之后,1.8之前,ConcurrentHashMap使用的是分段锁的方法,简而言之就是ConcurrentHashMap中启用了segment数组,并将map的元素通过再散列均匀的分布到segment中,一个segment就是一个锁。segment相当于一个小的hashmap,里面是数组+链表。通过把大的Hashmap分组,每个组使用一个锁,来缓解多线程访问被禁止的问题。那么不同的线程对不同的segment的操作是不会被禁止的。在这里插入图片描述

锁 + CAS

在jdk1.8之后 , ConcurrentHashMap的实现方法又从分段锁改为CAS+锁。从设置多个ReentranLock锁对象变为在直接锁链表的第一个元素,如果链表为空,就无需锁,直接用CAS插入。

代码如下:

 public V put(K key, V value) {
   
        return putVal
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值