2012-04-25 76 views
2

我有類似的代碼如下:爪哇:外部類和內部類之間的同步

class OuterClass 
{ 
    private final AtomicInteger count = new AtomicInteger(0); 

    private class InnerClass extends TimerTask 
    { 
     public void run() 
     { 
      ...... 
      ...... 
      incremenetCount(); 
     } 
    } 

    public void doSomething() 
    { 
     ....... 
     ....... 
     incremenetCount(); 
    } 

    private void incrementCount() 
    { 
     count.incrementAndGet(); 
    } 
} 

正在呼叫incrementCount從內部類一樣從外部類的任何其它函數調用它作爲同步實際上是圍繞變量count

+0

您可能會誤解此代碼。這裏沒有同步。 – 2012-04-25 04:53:27

+0

那麼,我沒有把代碼的減量部分作爲weel。 InnerClass擴展了TimerTask有兩種可能性,並且可能同時存在多次InnerClass的執行。另外,如果doSomething在同一時刻被外部類調用,則InnerClass正在調用incrementAndCount。 – Prasanna 2012-04-25 05:02:36

+0

我的觀點是,你似乎認爲這裏的一些代碼是同步的,否則不知道Java中的「同步」意味着什麼。在任何一種情況下,在嘗試編寫任何嚴重的多線程代碼之前,您應該閱讀Java併發性。 – 2012-04-25 05:11:54

回答

5

正在呼叫incrementAndCount從內部類一樣從外部類的任何其它函數調用它[...]

是,調用從內部類incrementCount()是相同的因爲從外面計數呼叫incrementCount()

所有非靜態內部類都有對封閉類的對象的隱式引用,並且通過此引用將調用incrementCount()

(故事會有所不同,如果你的內部類是靜態雖然

作爲同步實際上是圍繞着變盤點?

沒關係。無論您是從內部還是從外部類進行調用,都會對同一個對象調用同樣的方法。

+0

(如果內部類是靜態的,代碼將不能編譯,所以「故事」是沒有意義的。) – 2012-04-25 05:23:17

3

簡而言之,它是安全的。

要了解原因,讓我們來看看這個:

class SomeClass { 
    private final AtomicInteger count = new AtomicInteger(0); 
    ... 
    private void incrementCount() { 
     count.incrementAndGet(); 
    } 
} 

有跡象表明,需要考慮以確定這是否是線程安全的兩個問題。

  1. count的提取是否正確同步?回答是 - 因爲count被宣佈爲final,並且有規則說,一旦構造函數完成,就可以在沒有同步的情況下讀取final字段。

  2. incrementAndGet()方法是線程安全的嗎?回答是 - AtomicInteger班的規格說明如此。

現在讓我們看看內部類的情況。內部類的實例對外部類的實例有一個隱藏的最終引用。所以......

public void run() { 
     incrementCount(); 
    } 

相當於這個...

private final OuterClass $outer; // initialized by the constructor. 
    ... 
    public void run() { 
     $outer.incrementCount(); 
    } 

通過點1上方的推理,在incrementCount()調用本身是線程安全的。而$outer的提取也是線程安全的,因爲它隱含地是一個final字段。

+0

這是一個徹底的解釋。謝謝。 – Prasanna 2012-04-25 06:03:17