1

synchronizedメソッドまたはブロックには、「相互排除」と「可視性」という2つの機能があることを読みました。私は2つのことを知りたいです。

public class A{

  private final Object lock = new Object();
  private C obj = new C();

  public void methodA(){

      synchronized(lock){
        obj.x = 1;
        obj.y=3;
       }
    }

public void methodB(C obj2){

          synchronized(lock){
           obj2.x = obj.x;
           }


}

}

methodAタイプがグローバル共有オブジェクトを呼び出す2つのスレッドがAあり、がリリースされた後、lockによって取得されたと仮定します。これで、他のすべてのスレッドが変更を読み取りますか?つまり、ブロック内のすべての変更が表示されますか?または、Cオブジェクトを変更して、他の人に見えるようにする必要がありますか?thread1thread1lockobjsynchronizedvolatile

4

5 に答える 5

2

作成obj volatileすると、Cオブジェクトへの参照volatileが作成されます。つまり、同期されたブロックの外側に表示されます。そのオブジェクトのメンバーには影響しません。

つまり、objへの再割り当ては別のスレッドに表示されます。メンバーへの再割り当ては行われません。

于 2012-12-17T09:19:14.363 に答える
1

同期されたブロック内のすべての変更が表示されますか?

はい、それがアイデアです。JLS 17.45の定義では、関係の前に発生します。特に:

モニターのロック解除が発生します-そのモニターの後続のすべてのロックの前に。

したがって、thread2がロックを取得すると、同じロックを保持している間にthread1によって行われた変更が表示されることが保証されます。

Cオブジェクトを揮発性に変更して、他の人に見えるようにする必要がありますか?

volatileは、次のように記述した場合obj = new C();に、次の読み取りでobj新しいオブジェクトを参照していることを確認します。ただし、objの「コンテンツ」に関してはそのような保証はありません。したがって、次のように記述obj.x = someValue;した場合、objが揮発性であるため、変更が別のスレッドに表示されるという保証はありません。xあなたも揮発性にしない限り。

于 2012-12-17T09:19:21.393 に答える
1

これで、他のすべてのスレッドがobjへの変更を読み取ることがわかりますか?

そのロックの同期ブロック内のスレッドのみ。

同期されたブロック内のすべての変更が表示されますか?

たぶん。可視性を保証するには、スレッドが同期ブロック内にある必要があります。

または、Cオブジェクトを揮発性に変更する必要がありますか?

同期していない場合は役に立ちませんし、ここでは何の違いもありません。フィールドではなく、参照volatileの動作のみを変更します。obj

于 2012-12-17T09:21:48.390 に答える
0

いいえ、フィールドへのアクセスobjはまだスレッドセーフではありません。ロックオブジェクトの同期ではobj、このブロックののフィールドに値を書き込むためのスレッドセーフな操作のみが可能です。

UPDvolatileforobjは、このフィールド自体の参照値を変更しないため、役に立ちません。

于 2012-12-17T09:20:38.370 に答える
0

あなたの質問に答えるために、別の方法は、ロックなしで、変数objへのアクセスを単に与えることができます。objへのすべてのアクセスは、ロックによって慎重に保護する必要があります。これにより、objが(プログラマーによって定義されたように)一貫性のない状態にならないようにする必要があります。

あなたの特定の例では、それは私には十分に一貫しているように見えます。

于 2012-12-17T09:23:38.777 に答える