2

あなたが持っているとしましょう:

public class Foo {
    public Bar b;
}
public class Bar {
    public int x;
    public int y;
}

そして、次のように呼び出します。

Foo f = new Foo();
....
synchronized(f) {
   f.b.x = 3;
   f.b.y = 5; //x and y must be adjacent primes at all times.
}

スレッドセーフが深い場合は?つまり、synchronized(f) は、fb が更新されている間、別のスレッド (それ自体のsynchronized(f) ブロック内) が fb を認識できないようにしますか? 代わりに synchronized(this) を使用するのはどうですか?

4

2 に答える 2

6

同期が「深い」かどうかという質問は、Java スレッドの「同期」がどのように機能するかをまだ完全に理解していないことを示しています。すべての初心者 Java プログラマーは通常、同じ誤解を持っています。「同期すると、フィールドfへのアクセスがfスレッドセーフになります」。これは真実ではありません

1 つのスレッドがブロックを実行している場合、他のスレッドは同じオブジェクトのsynchronized(f)ブロックまたはメソッドに入ることができません。それがすべてです。synchronized

fで同期しての可変フィールドを保護しなければならない理由はありませんf。常に同じオブジェクトを使用し、のフィールドにアクセス/変更するときに常に同期する限り、任意のオブジェクトを同期できますf

逆に、 で同期することは、のフィールドへのアクセスが必ずしもスレッドセーフであるfことを意味しません。fプログラムの他の場所に他のコードを配置しfて、まったく同期せずに のフィールドを変更したり、別のオブジェクトで同期したりすることができます。

これが紛らわしいと思われる場合は、それが原因です。Java の設計者は (すべてのオブジェクトに暗黙のミューテックスを関連付けるという) 間違った選択をしたため、対処する必要があります。

于 2013-09-08T19:47:01.457 に答える