2013-12-10 65 views
0

不可變對象可以通過任何機制發佈 - 必須安全地發佈有效的不可變對象(靜態初始化,非易失性等) - '實踐中的Java併發性'。發佈不可變

class A{//immutable 
    final int i; 
    a(int i){ 
     this.i=i; 
    } 
    public int getI(){ 
     return i; 
    } 
} 

class B{ 
    A a=null; 
    public A getA(){ 
     if(a==null){ 
      a= new A(10); 
     } 
     return a; 
    } 
} 

如果B的實例線程之間共享;將不會有的局部構造的泄漏的可能性 - 雖然它是不可變的。
還是我明白這個錯誤?

+0

只有兩種可能性:1)a爲空2)a被完全構建 – hoaz

+1

您能否確保代碼先編譯? – skiwi

+0

讓我們假設A有一個比這更密集的建築。據我所知,建築本身不是一個原子操作。 – IUnknown

回答

1

A將被正確構建,因爲它的所有字段都是最終的。您遇到的問題是getA()上存在競爭條件,因爲它是懶惰的,但不是線程安全的。即不同的線程可以調用它並返回不同的對象。這些對象將是完整和正確的,但不是可能是意圖的那個。考慮以下內容

T1: if (a == null) 
T2: if (a == null) 
T3: if (a == null) 
T1:  a = new A(); 
T1: return a; 
T2:  a = new A(); 
T2: return a; 
T3:  a = new A(); 
T3: return a; 

所有三個線程都返回一個不同的對象。

+0

我已經提到了關於線程之間共享的B的相同'實例'。它會是相同的情況嗎? – IUnknown

+0

@IUnknown我假設只有一個'B'的實例。 –

+1

第二個線程可能不會看到'a'爲空 - 因爲A的構造不是原子的,'a'不是揮發性的? – IUnknown