[Java并发编程-4] 集合的线程安全及其解决方法

[Java并发编程-4] 集合的线程安全及其解决方法,第1张

文章目录
    • 问题说明
    • List集合三种解决方案
      • Vector
      • Collections
      • CopyOnWriteArrayList
    • Set集合的解决方法

问题说明

jdk中修改集合(如List, Set等)的方法都没有使用synchronize关键字, 在线程使用直接调用这些方法会产生线程安全问题(即同时访问数据会出错), 所以称这些类/接口是线程不安全的

比如下面执行ArrayList的add方法(线程不安全的):

public class ListAdd{

    private static final List<Integer> list = new ArrayList<>();

    public static void main(String[] args){
        for(int i = 0; i < 10; i ++){
            new Thread(() -> {
                list.add(1);
                System.out.println(list);
            }, "AAA").start();

            new Thread(() -> {
                list.add(2);
                System.out.println(list);
            }, "BBB").start();
        }
    }
}

结果有可能(也不一定)出现ConcurrentModificationException(并发修改)异常

List集合三种解决方案 Vector

来自jdk1.0古老的实现类, 在修改集合的方法(其他方法不需要使用)中使用了synchronize关键字

用Vector代替ArrayList,可以实现线程安全, 但是效率实在是太低了, 所以没啥人用

private static final List<Integer> list = new Vector<>();
Collections

另一个古老的解决方法, 和第一个意思差不多, 用另一种方法取代ArrayList(用的也少):

private static final List<Integer> list = Collections.synchronizedList(new ArrayList<>());

其实前面两种方法的原理都是实现了带有synchonize关键字的 *** 作方法

CopyOnWriteArrayList

使用了一种叫读时共享, 写时复制的技术, 这可不是什么同步技术了

意思是每次修改集合L时时, 会复制生成一个与原来集合相同的集合L1, 然后对L1进行修改, 这时读还是读原来的集合L, 当修改完成时,将两个集合合并成修改之后的集合

这个使用的比较多

可以读读源码理解一下:

Set集合的解决方法

类似的, HashSet也会产生线程不安全问题, 也有类似的解决方法,就是CopyOnWriteHashSet

用法不多解释, 瓢葫芦画瓢罢了

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/723690.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-26
下一篇 2022-04-26

发表评论

登录后才能评论

评论列表(0条)

保存