8实战java高并发程序设计---并行程序调试

8.1 准备实验样本


8.2 正式起航

首先,我们需要理解ArrayList的工作方式。在ArrayList初始化时,默认会分配10个数组空间。当数组空间消耗完毕后,ArrayList就会进行自动扩容。在每次add()函数时,系统总要事先检查一下内部空间是否满足所需的大小,如果不满足,就会扩容,否则就正常添加元素。多线程共同访问ArrayList的问题在于:在ArrayList容量快用完时(只有1个可用空间),如果两个线程同时进入add()函数,并同时判断认为系统满足继续添加元素而不需要扩容,那么两者都不会进行扩容操作。之后,两个线程先后向系统写入自己的数据,那么必然有一个线程会将数据写到边界外,从而产生了ArrayIndexOutOfBoundsException。

这个断点意味着在非主线程中(这里就是t1和t2了),当进入add()函数后,如果当前ArrayList的容量为9(当前的最大容量为10),则触发断点。

选中t1线程,让它进行容量检查,并让它在追加元素的语句前停止,如图8.10所示。

在t1增加元素之前,选中t2线程,并让t2进入add()函数完成容量检查,如图8.11所示。

此时,t1和t2都认为ArrayList中的容量满足它们的需求,因此,它们都准备开始追加元素。让我们先选择t1完成元素追加,如图8.12所示。

在t1追加完成后,t2并不知道数据空间实际上已经用完了。而之前的容量检查告诉t2,可以继续追加元素,因此t2还会义无反顾地继续执行追加操作。选择t2,让t2进行元素追加,此时,当t2试图向ArrayList追加元素时,追加操作并没有如我们预期一样完成,因为此时size的值已经超过了elementData的边界。从图8.13中可以看到ArrayIndexOutOfBounds-Exception异常位于t2线程中。

发布了33 篇原创文章 · 获赞 1 · 访问量 5513

猜你喜欢

转载自blog.csdn.net/ashylya/article/details/104520704