@
yeqizhang 我没有装 jdk7,看了下网上的文章及文中贴出的关键代码 transfer 方法。下面是我根据文章的理解。
关键代码 e.next = newTable[i]; newTable[i] = e;
transfer 中 table 是共享的,transfer 中只修改了 table 中 node 的 next 。next 会指向 newTable,newTable 也 可能 会通过 next 传播到线程外。
说可能是因为 线程 A 对 next 的修改不知道什么时候传播到线程 B 。线程 B 读到的 next 指向原来的 node,也可能指向线程 A 中 newTable 的 node 。
假设 table 中有一个 bin 是 a->b->c->null 。正常情况下,单线程 A 会把这个 bin 移到 newTable,变成 c->b->a->null 。
多线程情况下。线程 A 遍历到 b 了,产生的新链是 b->a->null 。
线程 B 开始遍历,这个时候线程 A 的修改还没传播到线程 B,所以线程 B 还是按 a->b->c->null 遍历。
当线程 B 移完了 a,新链是 a->null 。开始移 b 的时候,线程 A 的修改传播到线程 B 了,这时线程 B 就会按 b->a->null 遍历。
线程 B 按 b->a->null 遍历到 a 后,产生的新链就是 a->b->a 。这个就是环了。
即,正常按 a->b->c->null 遍历,翻转成 c->b->a->null ;多线程情况下,遍历到 b 时,变成按 a->b->a->null 遍历了。翻转的结果就是 a->b->a 了。
总结
单线程情况下 链表翻转了。多线程情况下,前面的线程正常翻转,后面的线程翻转到半途中链表已经变成了翻转后的,这时再翻转就是回头路了。