线程安全list_不安全的集合类学习子笔记

list

不安全类是什么?

不安全类是指在多线程并发的时候不能保证数据正确性的类,通常是由于这些类并没有加锁造成的。

为什么不设计成加锁的?

其实,在list之前有个集合类vector,它是内部加锁,它是一个线程安全类。不优先使用它的原因是加锁可以保证数据的正确性,但却降低了并发效率。list单线程安全,多线程不安全。并发条件下会产生ConcurrentModificationException异常(并发修改异常)

如何做到保证数据的正确性呢?

  1. vector替代list(并发效率低)
  2. 用Collections.synchronizedList(list)包装list(有synchronized修饰的方法效率低)
  3. 使用juc里的CopyOnWriteArrayList替代list(推荐使用)写入时复制,读写分离的思想。

CopyOnWriteArrayList 写时复制,读写分离

既能保证数据的正确性,又不会使并发效率变低。它的add源码:

public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            复制一个原来数组副本,在副本里“写入元素”,最后再用写完的副本替换原本的数组,即我们在
“写”时可以“读”,这两个操作所使用的不是一个数组,不会产生影响。
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

这样写时复制实现了读写分离,我们不需要在读的时候加锁(之前读需要加锁是因为读写不能同时进行,但一旦给读加了锁,那么读也不能同时进行,就降低了并发效率)

但是,我们每“写入”一个元素就要复制扩容一次数组,是非常耗时耗资源的,所以当我们需要写入较多数据的时候,CopyOnArrayList就不那么合适了。

Set

也是不安全的集合类

将不安全的集合变成安全集合的方法:

1.Set<String> set = Collections.synchronizedSet(new HashSet<>());
2.Set<String> set = new CopyOnWriteArrayListSet<>();

HashSet底层是什么?

//默认的空参初始化方法
public HashSet() {
	map = new HashMap<>();
}

//使用HashSet的add方法,依然是调用HashMap的底层put方法
public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

也就是说HashSet的底层就是HashMap

Map

也是不安全的集合类

变成安全的方法:

1.Map<String,String> map = Collections.synchronizedMap(new HashMap<>());

无论读取还是写入,都会进行加锁,当并发级别特别高,线程之间在任何操作上都会进行等待,效率低。
2.Map<String,String> map = new ConcurrentHashMap<>();

采用分段锁技术,其中Segment继承于ReentrantLock。不会像HashTable(线程安全) 那样不管是put还是get操作都需要做同步处理,理论上ConcurrentHashMap支持CurrentLevel(Segment数组数量)的线程并发。每当一个线程占用锁访问一个Segment时,不会影响其他的Segment.

节选自狂神说JUC学习笔记+补充(一)是其中的一部分,为方便阅读将其抽取出来,查看完整笔记见

演绎法5919:狂神说JUC学习笔记+补充(一)​zhuanlan.zhihu.com
973bf580b98e8dc0e11bcd7ad69aaf0c.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值