3

私はこのクラスを持っています:

public class MyClass {

    public MyClass(){}

    public void actionA(){
        synchronized(MyClass.class){
            System.out.print("A");
        }
    }

    public void actionB(){
        synchronized(MyClass.class){
            actionA();
        }
    }

}

どれが(もしあれば)本当ですか?

  1. actionA()はMyClass.classに関連付けられたロックを取得できないため、actionB()を呼び出すとデッドロックが発生します。
  2. actionB()を呼び出しても、MyClass.classに関連付けられたロックがすでに取得されているため、デッドロックは発生しません。
4

2 に答える 2

2

#2呼び出し元のスレッドにロックがあるため、発生します。

ただし、コードが次のようになっている場合:

public void actionB(){
    synchronized(MyClass.class) {
      Thread thread = new Thread(new Runnable { run() { actionA(); }});
      thread.start();
      thread.join();
    }
}

次に、デッドロックが発生します。locksスレッドごとに取得されます。

南京錠の共有キーのイメージが役立つと思います。一度に1つのスレッドのみがキーを持つことができますが、明らかに同じキーが適合するロックを開きます(キーは同じ同期オブジェクトを使用するすべてのロックに適合します)。

余談ですが、公開されているフィールドで同期することはお勧めできません。遠く離れた別のコードが同じオブジェクトをロックして、不要な競合やデッドロックを引き起こす可能性があるためです。

于 2012-05-18T12:51:59.557 に答える
2

#2起こります。

リエントラント同期

スレッドが別のスレッドが所有するロックを取得できないことを思い出してください。ただし、スレッドはすでに所有しているロックを取得できます。スレッドが同じロックを複数回取得できるようにすると、再入可能な同期が有効になります。これは、同期されたコードが直接的または間接的に、同期されたコードも含むメソッドを呼び出し、両方のコードセットが同じロックを使用する状況を示しています。再入可能な同期がない場合、同期されたコードは、スレッドがそれ自体をブロックしないようにするために、多くの追加の予防措置を講じる必要があります。

于 2012-05-18T12:54:43.210 に答える