并发下的ArrayList错误分析,并发arraylist错误
并发下的ArrayList错误分析,并发arraylist错误
目录
结果1.并发导致数据丢失
结果2.并发导致插入null
结果3.并发导致数组越界
分析:
直接看示例
public class ArrayListTest { private static List<String> threadList = new ArrayList<String>();
public static void main(String[] args) { try { testWriteArrayListError(); } catch (Exception e) { e.printStackTrace(); } } 原文:https://blog.csdn.net/lan861698789/article/details/81697409 /** * @Title: arraylist * @author: crazyJava * @Description: 测试并发对arraylist的影响 * @throws Exception * @return void */ private static void testWriteArrayListError() throws Exception {
Runnable writeR = new Runnable() { public void run() { threadList.add(Thread.currentThread().getName()); } };
for (int i = 0; i < 1000; i++) { Thread t = new Thread(writeR, i + ""); t.start(); }
// 等待子线程执行完 Thread.sleep(2000);
System.out.println(threadList.size()); // 输出list中的值 for (int i = 0; i < threadList.size(); i++) { System.out.println("index:" +i + "->" + threadList.get(i)); } } } |
结果1.并发导致数据丢失
结果2.并发导致插入null
996 index:0->0 index:1->1 ...... index:107->485 index:108->354 index:109->null index:110->479 |
结果3.并发导致数组越界
分析:
以添加为例,代码(JDK1.7):
原文:https://blog.csdn.net/lan861698789/article/details/81697409
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!!//代码1 elementData[size++] = e;//代码2 return true; } private void ensureExplicitCapacity(int minCapacity) { if (elementData == EMPTY_ELEMENTDATA) {//第一次add时候,初始化容量大小为: 默认值10 or minCapacity minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } modCount++; if (minCapacity - elementData.length > 0) {//判断是否需要扩容//代码3 int oldCapacity = elementData.length;//现在容量大小 int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容原来容量的1.5倍 if (newCapacity - minCapacity < 0) //如果扩容后还是不能满足,则当前容量设置为 需要插入的大小 newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);//数组的扩容 } } |
黄色部分(代码2)可拆分为两条语句:
elementData[size] = e; size ++; |
结果1和2原因:
假设初始size为0,elementData为空。
当线程A执行完elementData[size] = e;还未执行size++就停止了,此时,size=0; elementData[0]放的是A的value,
然后线程B正常完成一个add操作;此时size=1,elementData[0]里面放的是B的value,把A的value给覆盖了。
然后B继续执行size++; 此时,size=2了。数据结构如下:
结果3原因:
假设初始化size为9,elementData.length也为10,这里处于要扩容的临界点。
当线程A执行完代码1(ensureCapacityInternal(size + 1)),后暂停了。此时未扩容。
然后线程B也执行代码1(ensureCapacityInternal(size + 1)),也没有扩容,然后继续往后正常执行。此时size变为了10了。
然后线程A继续执行代码2,size先变为11,然后在赋值给elementData[10],此时就会抛出数据越界错误。
原文:https://blog.csdn.net/lan861698789/article/details/81697409
相关文章
- 暂无相关文章
用户点评