欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

多线程下List 如何解决不安全问题

程序员文章站 2022-05-04 08:50:16
什么是线程安全与不安全线程安全:就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。线程不安全:就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据为什么Lis是不安全的呢?show code ArrayList list = new ArrayList<>(); for (int i = 0; i < 30; i+...

什么是线程安全与不安全

线程安全:就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

线程不安全:就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据

为什么Lis是不安全的呢?show code

 ArrayList<String> list = new ArrayList<>();
 for (int i = 0; i < 30; i++) {
            new Thread(()->{
                list.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+list);
            },String.valueOf(i)).start();
        }

结果是
java.util.ConcurrentModificationException

为社么会这样?看看源码

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

我们可以看到,当添加元素之后,size还没有加加,如果此时另一个线程抢夺了cpu的资源,进行添加元素操作,size现在也是为0,然后之前的线程两个线程继续执行,结果就是有两个元素添加进去,但是当前容量为却是1.明白了吗

那么如何解决呢?
使用 Vector
为什么vector可以呢,看看源码

public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }

还可以有其他方式吗?
可以的,使用集合工具类 Collections.synchronizedList(new ArrayList<>()) 就可以创建一个安全的list,看看源码是怎么实现的

 public void add(int index, E element) {
            synchronized (mutex) {
          		  list.add(index, element);
            }
        }

你说如果不想使用这个,还有没有其他的方法,还有哦
在java.util.concurrent的包下有 CopyOnWriteArrayList ,采用了读写分离思想,我们使用这个也是可以的,建议使用,我们来看看它的源码

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();
        }
    }

map 和 set 也存在不安全问题哦,解决方式也类似

本文地址:https://blog.csdn.net/qq_42224683/article/details/107335381