2012-04-25 11 views
2

私は次のようなコードがあります。のJava:外部クラスと内部クラス間の同期

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

あなたはこのコードについて何か誤解している可能性があります。ここには同期がありません。 –

+0

さて、私は、コードの減分部分を小屋として置いていませんでした。 2つの可能性があります。InnerClassはTimerTaskを拡張し、複数のInnerClassの実行が同時に存在する可能性があります。また、同じ瞬間に外部ク​​ラスによってdoSomethingが呼び出された場合、InnerClassはincrementAndCountを呼び出しています。 – Prasanna

+0

ここでのいくつかのコードは同期されていると思うか、Javaでの "同期"の意味を知らないように思えます。いずれの場合でも、深刻なマルチスレッドコードを書く前に、Javaの並行性を読み出す必要があります。 –

答えて

5

はい、内部クラスからincrementCount()を呼び出すことと同じです

[...]外側のクラスの他の関数からそれを呼び出すのと同じ内部クラスからincrementAndCountを呼んでいます外側のカウントからincrementCount()を呼び出す。

すべての非静的内部クラスは、囲むクラスのオブジェクトへの暗黙の参照を持ちます。この参照を通じて、incrementCount()が呼び出されます。同期として

(あなたの内部クラスはしかし静的した場合は別の話をされていると思います。)

は、変数countの周りに実際にありますか?

重要ではありません。内側または外側のクラスから呼び出しを行った場合でも、同じメソッドが同じオブジェクトで呼び出されます。

+0

(内部クラスが静的だった場合、コードはコンパイルされないので、 "ストーリー"は意味がありません) –

3

短い答えは安全だということです。

、これを見てすることができます理由を理解するには、次の

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

これは、スレッドセーフであるかどうかを判断するために検討する必要がある2つの質問があります。

  1. countのフェッチは適切に同期されていますか? yesと答えます。countfinalと宣言されており、コンストラクタが完了すると、finalフィールドは同期せずに読み取ることができるというルールがあります。

  2. incrementAndGet()メソッドはスレッドセーフですか?答えはyesです - AtomicIntegerクラスの仕様はそう言います。

ここで、内部クラスのケースを見てみましょう。内部クラスのインスタンスには、外部クラスのインスタンスへの非表示の最終参照があります。だから... ...

public void run() { 
     incrementCount(); 
    } 

これに相当します...上記の点1の推論による

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

incrementCount()コール自体はスレッドセーフです。暗黙的にfinalフィールドなので、$outerのフェッチもスレッドセーフです。

+0

これは完全な説明でした。ありがとう。 – Prasanna

関連する問題