ArrayList不是线程安全的链表。 线程安全的意思就是多个线程访问相同数据时,无论怎么访问,数据的状态都要保持一致(和一个线程单独访问的结果是一样的)。 比如说,有两个线程,一个线程对同一个整数变量自增运算100次,另一个线程对同一个整数变量自减50次,如果算法是线程安全的,那么,两个线程同时运行之后,结果和单独一个线程先自增100次再自减50次是一样的。这就要求,每一次的自增(自减)操作,都是线程安全的才可以。 楼主可能不太理解,为啥两个线程同时访问同一个内存变量会出现差错。这是由于线程切换和多CPU的缓存造成的。一般都解释为线程切换造成的。 这是一个比较讲究细节的过程,一个线程运行的时候,同一时间另一个线程可能没有处于运行状态。操作系统中有两三千个线程需要运行,CPU核心数也就那么几个,所以要轮着来使用。线程切换的时候,需要先将要换出去的线程进行现场保护,将当时的线程状态保存起来,包括CPU寄存器中的数据,会被压入线程栈中,之后再将切换进来的线程进行现场还原,从线程栈中把CPU寄存器的数据还原回去。我们知道,CPU做的算术运算和逻辑运算都是在寄存器之间做的,做完之后再回写到内存中。这样的话,寄存器的数据相当于内存数据的一个镜像。多个线程访问同一个内存数据,就会有多个镜像,那么,在线程切换的时候,镜像没来得及回写到内存就被压栈了,其他线程更改镜像有的就可以及时回写,等刚才那个没来得及回写的线程被恢复运行时,第一件事就是回写他上一次执行的镜像,那么,其他线程的镜像被覆盖掉了,最终造成了内存数据的不一致。 多CPU时,由于每块CPU都自带缓存cache,也会造成这种现象。 我之所以写这些,就是因为,楼主在表述问题时,把程序正在操纵的数据与链表混为一谈,细节上,两者是截然不同的东西,虽然,你的代码操纵的就是链表,但是,实际上,操纵的是链表里面的东西(内容结构)。链表被覆盖指的是链表的引用被其他东西覆盖了,和链表内部,指向链表元素的引用被其他东西所覆盖,是两个概念。而且,不单单是引用,链表的大小也会产生线程安全的问题,所以,整个链表就不是线程安全的
public boolean add(E e) { modCount++; add(e, elementData, size); return true; }
[quote=引用 4 楼 qq_45962712 的回复:] 那个前辈,你说刷新主存,如果线程按照你上面的流程执行的话,是不是当线程a刷新主存的时候,会把前面线程b所做的工作给覆盖掉,比如当线程b在add的时候,就刷新主存,之后这时候,集合有一个元素,并且size等于1,之后线程a再刷新主存,这时候就把集合就被刷没了,并且size也等于0了
那个前辈,你说刷新主存,如果线程按照你上面的流程执行的话,是不是当线程a刷新主存的时候,会把前面线程b所做的工作给覆盖掉,比如当线程b在add的时候,就刷新主存,之后这时候,集合有一个元素,并且size等于1,之后线程a再刷新主存,这时候就把集合就被刷没了,并且size也等于0了
[quote=引用 3 楼 qq_45962712的回复:][quote=引用 1 楼 weixin_43845112的回复:]主要问题是在于list不是线程安全的,可以这样理解:线程A主存读取当前size 0,add 1 remove 0,但是并不刷新主存,线程B主存读取size 0 add 1 刷新主存,此时线程A也刷新主存,导致最终的size是0 线程B再执行remove操作的时候,有可能先从主存同步数据,拿到size 0。 线程从主存同步数据和修改后将数据同步回去的时机是随机的
为什么这段代码会有线程安全问题呢 这里为什么会有线程安全问题啊,按着这样的调用,无论那个线程remove()的时候,集合里面都会有一个元素,因为是先加后remove 怎么可能发生执行到remove的时候,集合没元素,就算一个线程没加上,另外一个线程也加上了啊
[quote=引用 1 楼 weixin_43845112的回复:]主要问题是在于list不是线程安全的,可以这样理解:线程A主存读取当前size 0,add 1 remove 0,但是并不刷新主存,线程B主存读取size 0 add 1 刷新主存,此时线程A也刷新主存,导致最终的size是0 线程B再执行remove操作的时候,有可能先从主存同步数据,拿到size 0。 线程从主存同步数据和修改后将数据同步回去的时机是随机的
主要问题是在于list不是线程安全的,可以这样理解:线程A主存读取当前size 0,add 1 remove 0,但是并不刷新主存,线程B主存读取size 0 add 1 刷新主存,此时线程A也刷新主存,导致最终的size是0 线程B再执行remove操作的时候,有可能先从主存同步数据,拿到size 0。 线程从主存同步数据和修改后将数据同步回去的时机是随机的
62,635
社区成员
307,269
社区内容
加载中
试试用AI创作助手写篇文章吧