优秀的编程知识分享平台

网站首页 > 技术文章 正文

ArrayList线程不安全的案例分析(arraylist线程不安全为什么还要用)

nanyue 2024-08-12 22:31:11 技术文章 6 ℃

在java的项目开发中,我们工作中使用最多的集合应该就是ArrayList了,

但是你可知ArrayList是线程不安全的,平时我们使用时都是单线程或者线程数比较少的情况,

这种情况ArrayList一般都不会出现问题,但是线程一旦多起来,问题就很容易爆发了

如下面的多线程案例

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class ListTest {
    private static final int threadNum = 20;
    
    static List list =new ArrayList();
    static CountDownLatch latch = new CountDownLatch(20);
    
    public static void main(String[] args) {
        
        for (int i = 0; i < threadNum; i++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 0; i < 1000; i++) {
                        list.add(i);
                    }
                    latch.countDown();
                }
            });
            thread.start();
        }
        
        try {
			latch.await();//等待所有线程完成
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
        System.out.println("list中总数量===="+list.size());
    }
}

正常结果应该打印20000,可是每次运行的结果确实抛出异常java.lang.ArrayIndexOutOfBoundsException

这是什么原因呢?

这是因为ArrayList底层是数组,每次add时,执行 element[i++]=a,

而element[i++]=a在cup层是分两步进行的

1. element[i]=a

2. i=i+1

但由于多线程运行时,假设数组的长度一开始等于2,i等于1,数组还剩一个元素可放入,A线程刚进入add方法时,还没来得及执行步骤1, cup就让他暂停,此时线程B运行了,依然是i=1,执行1、2步骤后,i变成了2,

等到A线程运行1时,element[2]=a 就发生越界了。

这就是线程不安全了,假设线程在进入add之前就已经发现数组长度不够,ArrayList就会进行扩容,就不会发生这种情况了

怎么解决呢

这就是本次的主角Vector上场了

只需要就static List list =new ArrayList();换成 static List list =new Vector();就可以保证线程安全了

最近发表
标签列表