9

次の呼び出しが再入可能かどうか教えてください。

public class Foo {

  public synchronized void doSomething() {}

  public synchronized void doAnotherSomething() {}
}

public class Too {

  private Foo foo;

  public synchronized void doToo() {
    foo.doSomething();
    //...other thread interfere here....
    foo.doAnotherSomething();
  }

}

doToo()メソッドの再入可能での2つの連続呼び出しはありますか? foo.doSomething()メソッドが固有のロックを取得して解放し、2 つの呼び出しの間にネストされた同期がないため、このケースについてはわかりません。2 つの呼び出しの間に他のスレッドが干渉する状況はありますか?

4

3 に答える 3

32

まず、Java の再入可能ロックについて:

Java の同期ブロックは再入可能です。これは、Java スレッドがコードの同期ブロックに入り、それによってブロックが同期されているモニター オブジェクトをロックした場合、そのスレッドは、同じモニター オブジェクトで同期されている他の Java コード ブロックに入ることができることを意味します。

ここから撮影。

( で) 説明した 2 つの連続した呼び出しは、別のオブジェクトがの privateへのdoToo参照を持っていない限り、干渉されません。これは、 にアクセスするには、 をロックする必要があるためです。ただし、呼び出しごとにロックが取得および解放されるため、呼び出しは再入を呼び出しません。呼び出された場合、またはその逆の場合、それらは再入可能になります。TooFoofooToodoSomethingdoAnotherSomething

于 2012-08-31T16:42:16.687 に答える
5

それは、他のスレッドがアクセスしているものに完全に依存します。これらの関数間で別のスレッドが CPU を引き継ぐことはできますか? はい。競合状態は発生しますか? 多くの要因に依存します。

あなたが投稿したものから、foo.doSomethingはfooでロックされてから解放され、doAnotherSomethingに入ると再びロックされます。したがって、同じ Too オブジェクトでロックされていない別のスレッドが foo を操作しようとすると、doSomething と doAnotherSomething の間でそれを行うことができます。基礎となる foo オブジェクトを操作する前に全員が同じ Too オブジェクトで同期した場合、Too オブジェクト メソッドは完了するまで他のスレッドをブロックするため、foo のこれら 2 つのメソッドは呼び出し間で操作される状態を持ちません。したがって、問題があるかどうかは、他のアクセサに依存します。

あなたが投稿したものからここに再入はありませんが、Amirが投稿したようにJavaは再入可能同期で問題ありません。

于 2012-08-31T16:47:25.590 に答える
4

まず、ロックはオブジェクトに適用されるため、オブジェクトを作成してからロックを適用する必要があります。

are 2 continuous invocations in method doToo() reentrant? I

あなたの場合、それらは re-entrant ではありません。コードが以下のようなものである場合、それらは再入可能になります。

  public class Foo {

 public synchronized void doSomething() {
        doAnotherSomething();
}

 public synchronized void doAnotherSomething() {}
}

1 つのオブジェクトでロックが取得されると、同じオブジェクトで上記の場合のようにトラバースできます。

于 2012-08-31T16:46:05.513 に答える