[英]Why can't complexity of ConcurrentLinkedQueue.size() be constant?
[英]Impossible (?): NullPointerException on ConcurrentLinkedQueue.size()
我在IBM JVM上获得了这个NPE, 1.6 :
java.lang中。 java.util.concurrent.ConcurrentLinkedQueue.size上的java.util.concurrent.ConcurrentLinkedQueue.first( ConcurrentLinkedQueue .java: 274 )中的NullPointerException (ConcurrentLinkedQueue.java:315)。 。 。
相关的来源显示第274行抛出一个空的“ 头 ”成员。 搜索用法显示此成员根据需要设置为新节点(),但永远不会无效。
怎么会这样? 我错过了什么?
...在调试模式下,我无法重现这一点。 可以从多个线程访问此队列。
片段(除了更改行号的注释之外,Sun和IBM的来源相同):
Node<E> first() {
for (;;) {
Node<E> h = head;
Node<E> t = tail;
Node<E> first = h.getNext(); // line #274 on IBM, #263 on Sun
...
}
}
像这样的错误通常来自JIT编译器,它会使一些神秘的优化错误。
你几乎无能为力; 与IBM的日志错误,他们将指导您完成如何收集足够的信息以调试问题的过程。
注意:在过去几年中,我们提交了两个这样的问题。 因此,即使考虑到IBM在其VM上花费的巨大测试工作,它们也并非罕见。
一个不起眼的场景可能导致这种情况:
A类包含一个静态队列,可能需要一段时间才能初始化。
class A {
// Long process which makes a second thread access `q` while it is still being constructed.
public Object o = aLongProcess();
public static Queue q = new ConcurrentLinkedQueue<String>();
B类访问队列。
class B {
...
void doSomething () {
String s = A.q.first();
}
线程T1首先访问A类 - 从而开始其初始化过程。
Object o = A.o;
线程T2在仍处于初始化状态时访问队列。
B b = new B();
b.doSomething();
所以基本上你是在看两个线程之间的竞争条件,其中一个人认为队列被初始化而另一个人仍在制造它。
请注意,仅仅因为对象名称以Concurrent
开头并不意味着对象的所有功能都是线程安全的。
我想另一种选择可能是你只保留对队列的弱引用,并且你试图在GC之后访问它,但我希望你会在你的问题中提到它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.