p.casNext诡异问题排查
idea debug/run返回不同结果
在ConcurrentLinkedQueue源码调试中发现run/debug这两个问题出现不同结果的问题 。 相当诡异!!!
随后只能将代码抽离出来进行排查。
public boolean offer(E e) {
final Node<E> newNode = new Node<E>(e);
Node<E> t = tail, p = t;
Node<E> q = p.next;
if (q == null) {
if(p.casNext(null,newNode)){
System.out.println(p.next ==p); //1
if (p != t) // hop two nodes at a time//2
casTail(t, newNode); // Failure is OK.
return true;
}
}
发现只要断点打在1处就有问题 p.next =p 为true 然而在点2处正常。
可能有一下问题:
- toString()调用某个方法
- IDE debug模式调用了某个方法
验证思路
在可变状态方法中增加调试信息
结果
发现first()被多次调用。为了更好了解调用信息 加上调用信息 代码如下:
System.out.println("-----------------------------------------------------------------");
StackTraceElement stack[] = Thread.currentThread().getStackTrace();
for (int i = 0; i < stack.length; i++) {
System.out.println(stack[i].getClassName() + " -->" + stack[i].getMethodName()+" " +stack[i].getLineNumber() );
}
System.out.println("-----------------------------------------------------------------");
debug时日志打印
java.lang.Thread -->getStackTrace 1559
com.ly.lock.ConcurrentLinkedQueue -->first 188
com.ly.lock.ConcurrentLinkedQueue -->isEmpty 214
com.ly.lock.ConcurrentLinkedQueue -->offer 103
com.ly.lock.ConcurrentLinkedQueue -->main 773
java.lang.Thread -->getStackTrace 1559
com.ly.lock.ConcurrentLinkedQueue -->first 188
com.ly.lock.ConcurrentLinkedQueue -->size 235
com.ly.lock.ConcurrentLinkedQueue -->offer 103
com.ly.lock.ConcurrentLinkedQueue -->main 773
java.lang.Thread -->getStackTrace 1559
com.ly.lock.ConcurrentLinkedQueue -->first 188
com.ly.lock.ConcurrentLinkedQueue -->toArray 374
com.ly.lock.ConcurrentLinkedQueue -->offer 103
com.ly.lock.ConcurrentLinkedQueue -->main 773
结论
结果很清晰 在debug时 IDE会自动调用toArray、size 、isEmpty方法从而调用first()方法 查看first会发现 该方法会重新设置头结点 h.lazySetNext(h); 所以造成debug,RUN模式结果不一致这一诡异情况。