5

次のことを考慮してください。

public class Deadlock {
static class Friend{
    private final String name;

    public Friend (String name){
        this.name = name;
    }

    public String getName(){
        return this.name;
    }


    public synchronized void bow(Friend bower){
        System.out.format("\n%S: %S has bowed to me!" , this.name, bower.getName());
        bower.bowBack(this);
    }
    public synchronized void bowBack(Friend bower) {
        System.out.format("\n%S: %S has bowed back to me!", this.name, bower.getName());
    }


}

public static void main(String[] args) {
    final Friend alf = new Friend("Alf");
    final Friend arian = new Friend("Arian");

    // Thread 1
             new Thread(new Runnable()  {
        public void run(){ alf.bow(arian);}}).start();

    //Thread 2
    new Thread(new Runnable()  {
        public void run(){ arian.bow(alf);}}).start();  
}

}

出力は

ALF:ARIANは私に頭を下げました!ARIAN:ALFは私に頭を下げました!

LOCK状況.....

スレッド1を実行するときは、オブジェクトFriendをロックする必要があります。その直後、スレッド2は2番目のオブジェクトをロックする必要があります。これで、メソッドbow はスレッド1によってロックされ、「ALF:ARIAN has bowedtome!」と出力されます。どうしてスレッド2はに入り、どちらも* bowBack *に入ることができないのですか?

よろしくB。

4

4 に答える 4

5

synchronizedメソッドは常にで同期されることに注意してくださいthis

2つのオブジェクトがあるため、2つのロックがあります。sロックをalf.bow()取得し、sを取得します。しかし、デッドロックが発生したときに、もう一方を取得しようとします。alfarian.bow()arianbowback()

共有ロックオブジェクトで同期する場合は、次のようにする必要があります。

class Friend {
   private static final Object lock = new Object();

   public void bow(...) {
     synchronized( lock ) {
        ...
     }
   }

   public void bowback(...) {
     synchronized( lock ) {
        ...
     }
   }

}

lockは静的フィールドにあるため、すべてのインスタンスが同じロックオブジェクトを使用することを意味します。Friendしたがって、デッドロックが発生する可能性はありません。

クラスオブジェクトsynchronized( Friend.class ) {...}で同期することもできますが、コードの他の部分がロックを盗まないという保証がないため、外部から見えるオブジェクトで同期することは通常はお勧めできません。

于 2012-11-26T10:16:32.867 に答える
3

同期は任意のオブジェクトを使用して行われます。スレッドが異なるオブジェクトと同期されている場合、スレッドは同期されたブロックに同時に入ることができます。

インスタンスメソッドのsynchronizedキーワードは、ブロックがそのインスタンスによって同期されることを意味します。2つの異なるオブジェクトのメソッドを呼び出しているためbow、両方がそのような関数を同時に実行するコントロールはありません。

クラスオブジェクトによって同期します(または、そのために作成された静的なfinalオブジェクトを使用します)。

于 2012-11-26T10:19:15.840 に答える
1

-を使用しましたが2 objectsここの両方のスレッドは2つの異なるモニターロックを使用しています。

-両方のスレッドがロックされて2 different objectいるため、オブジェクト1でスレッド1をロックしても、オブジェクト2をロックするスレッド2に影響がないことは明らかです。

-ここでオブジェクトロックsynchronizedを必要とするキーワードを使用し、両方のスレッドに独自のオブジェクトロックを提供しているため、スレッド2が弓に入ります。

于 2012-11-26T10:19:22.880 に答える
1

共通のオブジェクトをロックする必要があります。

public static void main(String[] args) {
    final Object lock = new Object();
    final Friend alf = new Friend("Alf", lock);
    final Friend arian = new Friend("Arian", lock);
    ...  
}


public  void bow(Friend bower){
    synchronize(lock){
        System.out.format("\n%S: %S has bowed to me!" , this.name, bower.getName());
        bower.bowBack(this);
    }
}
public void bowBack(Friend bower) {
    synchronize(lock){
        System.out.format("\n%S: %S has bowed back to me!", this.name, bower.getName());
    }
}
于 2012-11-26T10:31:12.093 に答える