2012-04-19 2 views
0
public Foo getFoo(){ 
    Foo foo = null; 

    synchronized(fooList){ 
     if(fooList.size() > 0){ 
      foo = fooList.remove(0); 
     } 
    } 

    return foo; 
} 

fooはsynchronizedブロックの外で宣言されているため、不良データを返す可能性はありますか?戻り値が同期ブロック外で宣言/返される場合、メソッドはスレッドセーフですか?

+0

これは大丈夫ですが、あなたが与えた例は 'foo'の存在を促しません。あなたの文脈で 'return fooList.remove(0)'と言うだけでいいですか? –

+0

@MarkoTopolnik、これは伝統的なコードです。 :D – user1329572

答えて

3

getFoo()を呼び出す各スレッドインスタンスは、独自のfooインスタンスを持ちます。したがって、fooはスレッドセーフであり、同期は必要ありません。

1

ここで「不良データ」とは何ですか? fooListは、synchronized(fooList)の前に、そして対応する閉じ括弧の後で、return foo;(より一般的に言えば、返された値が使用されるまで)に非同期に変更されることがあります。 Foo fooがローカル変数でありfooList

ローカル変数は、各スレッドの呼び出しではなく、単一のオブジェクトを共有する、新しいFooオブジェクトが作成されますので、スレッドセーフで同期しているので、

+0

このメソッドが 'null'を返す場合、ロジックは' fooList'が空であるということです。 'fooList'が空でないときにこのメソッドが' null'を返さないようにしたいと思います。 – user1329572

+1

OK私はポイントを得る。 'fooList'のためにモニタをロックした時点で空ではない(そして' fooList'へのすべてのアクセスはそれに同期しています!)、あなたは決して 'null'を取得しません。 –

1

getFooは、古いデータを返しません。変数はスレッドセーフではありませんが、複数のスレッドがfooListにアクセスできますが、この場合はfooListが既に同期されているためです。

+0

ローカル変数は本質的にスレッドセーフですか? – user1329572

+1

@ user1329572私の更新された回答を参照 –