ArrayList在添加元素的时候会出现的一些线程不安全的现象

再学习多线程编程的时候,看到如下代码。


package com.cbf4life;

import java.util.*;

public class ThreadSafeDemo {
    public ThreadSafeDemo() {

        ThreadGroup group=new ThreadGroup("testGroup");

        MyThread at=new MyThread();

        for(int i=0;i<10000;i++){
            Thread th=new Thread(group,at,String.valueOf(i));
            th.start();
        }

        while (group.activeCount() > 0) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        System.out.println(at.list0.size());
        System.out.println(at.list0.get(0));

    }

    public static void main(String[] args) {
        new ThreadSafeDemo();
    }

    class MyThread implements Runnable {

        List<String> list0=new ArrayList<String>(); //thread not safe
//        Vector<String> list0=new Vector<String>(); //thread not safe
//        List<String> list0=Collections.synchronizedList(new ArrayList<String>()); //thread safe
        public void run() {
            try {
                Thread.sleep((int)(Math.random()*2));
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            list0.add(Thread.currentThread().getName());
        }
    }
}

这段代码的原意是举例说明ArrayList是线程不安全的,然后在运行的时候可能会出现多种结果,

第一种结果

9976
0

大致原因是list的add方法导致的。

/**
 * Appends the specified element to the end of this list.
 *
 * @param e element to be appended to this list
 * @return <tt>true</tt> (as specified by {@link Collection#add})
 */
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}
这个是list的add方法,
elementData[size++] = e;

这一段代码块就是问题所在,size++这个过程可以分为三步

1.从内存中取到size的值。

2.计算size的值。

3.将size的值写到内存当中。

这不是一个原子性的操作,当多线程添加的情况下,假如size=0时,添加第一个元素的线程添加成功,同时在size没有及时写到内存中时,这时另一个线程继续添加就覆盖了原来的值导致最终list的值为9976。



第二种结果

9976
1

按道理说结果应该是9976 0,但是还是上面说的原因,原来的0被1覆盖了。


第三种结果

数组下标越界异常

原因可能出现在数组扩容的时候,假如当前数组的大小为8,而我添加第7个元素的时候,数组当前不需要扩容。然后这个线程进入阻塞,另一个线程也添加元素,发现当前数组大小还有一个容量,于是添加成功已经有8个元素,然后前一个阻塞线程开始添加元素,然后数组没有扩容,所以数组就容不下这个元素,于是数组下标越界了。


这个例子是在说明ArrayList的非线程安全的特性。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值