线程安全的Map——Hashtable、SynchronizedMap、ConcurrentHashMap线程安全原理

本文参考自:Hashtable, Collections.SynchronizedMap和ConcurrentHashMap线程安全实现原理的区别以及性能测试_IamHYN的博客-CSDN博客

Java集合常见面试题总结(下) | JavaGuide(Java面试 + 学习指南)

Hashtable

底层数据结构和JDK1.8之前的HashMap一样,是数组+链表。确保线程安全就是在每个方法前加synchronized关键字,即使只是读取数据也会用锁锁住整个对象,并发性很差。

Collections.SynchronizedMap

SynchronizedMap 是 Collections 集合类的私有静态内部类,主要用于将不安全的map包装成安全的map。SynchronizedMap 成员变量包含一个Map类型m用来接收传入的Map对象,一个Object类型的mutex用来充当锁。实现线程安全的方法就是先对mutex上锁,然后执行m的相关方法。和Hashtable一样,同一时刻只能有一个线程调用其方法,并发性能差。

SynchronizedMap成员变量及其构造函数:

private static class SynchronizedMap<K,V> implements Map<K,V>, Serializable {
        private static final long serialVersionUID = 1978198479659022715L;
    	  // 用于接收传入的Map对象,也是类方法操作的对象
        private final Map<K,V> m;     
    	  // 锁对象
        final Object mutex;   
  
  			// 以下是SynchronizedMap的两个构造方法
        SynchronizedMap(Map<K,V> m) {
            this.m = Objects.requireNonNull(m);
            mutex = this;
        }
        SynchronizedMap(Map<K,V> m, Object mutex) {
            this.m = m;
            this.mutex = mutex;
        }
}

ConcurrentHashMap

JDK1.8之前

底层数据结构ConcurrentHashMap是由Segment数组结构和HashEntry数组结构组成。Segment扮演锁的角色,而且其继承了ReentrantLock,所以是一种可重入锁。HashEntry用于存储键值对数据,每个HashEntry数组属于链表结构。

线程安全实现方式:ConcurrentHashMap采用分段锁,就是对每个Segment数组元素加锁,Segment的个数一旦初始化就不能改变默认大小是16,也就是说默认可以同时支持16个线程并发写。

JDK1.8及以后

底层数据结构:跟HashMap JDK1.8的HashMap结构类似,采用数组+链表/红黑二叉树,链表长度大于8时转换成红黑树。

线程安全实现方式:采用Node+CAS+synchronized+volatile来保证并发安全。value用volatile关键字修饰,读取靠volatile保证线程安全。添加或修改时用synchronized关键字锁定当前链表或红黑二叉树的首节点,保证线程安全,此外还用到大量的CAS操作。JDK.8中对Node元素加锁,锁粒度更细,并发度更高,而且只要不发生哈希冲突,就不会影响其他Node的读写。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值