private transient volatile Node<E> head;
private transient volatile Node<E> tail;
public ConcurrentLinkedQueue() {
head = tail = new Node<E>(null);
}
public boolean offer(E e) {
checkNotNull(e);
final Node<E> newNode = new Node<E>(e);
for (Node<E> t = tail, p = t;;) {
Node<E> q = p.next;
if (q == null) {
if (p.casNext(null, newNode)) {
if (p != t)
casTail(t, newNode);
return true;
}
}
else if (p == q)
p = (t != (t = tail)) ? t : head;
else
p = (p != t && t != (t = tail)) ? t : q;
}
}
boolean casNext(Node<E> cmp, Node<E> val) {
return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
}
使用 ConcurrentLinkedQueue()
构造一个对象,并首次调用 offer()
方法
当代码执行到 if (q == null)
时,head == tail,但是当执行完 p.casNext(null, newNode)
,为什么是 head
成为了 { item = 1, next = null },也就是 newNode
,而 tail
变成了 { item = null, next = tail ( tail 本身) } ?
p 是从 t 赋值来的,而 t 是从 tail 赋值来的,tail == head,为什么调用 p.casNext(null, newNode)
会同时改变 head 和 tail 的值,且 head 和 tail 的值不一样了?
1
XYxe 2021-10-12 12:44:08 +08:00 1
|
2
GiftedJarvis OP @XYxe 十分感谢,困扰两天了,根本没往 IDEA 的问题上面想
|
3
Chinsung 2021-10-12 17:18:20 +08:00 1
@GiftedJarvis 之前遇到过一个类似问题,某个很 SB 的框架类在 toString 里面修改了对象的值,debug 阶段 idea 会调用 toString 以输出对象的 view,然后 debug 半天一直发现值和预想的不一样。
|
4
huang119412 2021-10-13 10:44:27 +08:00
老问题了 https://juejin.cn/post/6844904177437523982 不仅 idea 有问题
|
5
GiftedJarvis OP 各位大佬, 关闭 IDEA Debugger toString 后确实解决问题了, 这是新的结果:
初始化 head { item = null, next = null } tail { item = null, next = null } 第一次添加值完成后 head { item = null, next = { item = 1, next = null } } tail { item = null, next = { item = 1, next = null } } 第二次添加值完成后 head { item = null, next = { item = 1, next = { item = 2, next = null } } } tail { item = 2, next = null } 第三次添加值完成后 head { item = null, next = { item = 1, next = { item = 2, next = { item = 3, next = null } } } } tail { item = 2, next = { item = 3, next = null } } 第四次添加值完成后 head { item = null, next = { item = 2, next = { item = 3, next = { item = 4, next = null } } } } tail { item = 4, next = null } 然后, 有了新的疑问, 为什么要这样设计呢? tail 并不一定是尾结点, 为此还需要重新确定尾结点, 难道是因为性能吗? 这样可以少进行一次 casTail(t, newNode), 但代码可读性真的降低了好多呀 |