2012-11-26 11 views
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です:牡羊座生まれの私にお辞儀しています! アリラン:ALFは私に弓を掛けました!

LOCK状況.....

スレッド1つの実行は、そのオブジェクトの友達のロックを必要とします。その直後に、スレッド2は第2のオブジェクトをロックする必要があります。今度は、方法の弓はスレッド1によってロックされているので、 "ALF:ARIANが私に弓をかけました!スレッド2はどのように入力されますかいずれも入力できません* bowBack * ??

​​メソッドは常にthisで同期することを念頭に置いよろしくB.

答えて

5

ベア。

2つのオブジェクトがあり、したがって2つのロックがあります。 alf.bow()alfのロックを取得し、arian.bow()arianを取得します。しかし、bowback()は、デッドロックが発生したときにもう一方を取得しようとします。あなたが共有ロックされたオブジェクトで同期したい場合は

は、あなたがこのような何かをする必要があります

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

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

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

} 

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

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

+0

多くのご意見ありがとうございます。 –

3

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

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

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

1

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

-両方のスレッドが2 different objectのロックを行っているように、その対象物1のねじ1のロックは、オブジェクト2のロックを取るスレッド2に影響を及ぼさないことが一目瞭然。

-あなたがここにオブジェクトのロックを必要と​​キーワードを使用している、とあなたは、自分のオブジェクトのロックとスレッドの両方を提供しているので、2は弓を入力してくださいスレッド。

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()); 
    } 
} 
関連する問題