![](/img/trans.png)
[英]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.