0

デッドロック状態を実装しようとしていますが、どういうわけかそれを機能させることができません。Thread1 と Thread2 の両方のスレッドが run 関数に入りますが、誰が最初に run に入ったかに応じて、そのうちの 1 つだけが Sub/Sum に入ります。例: スレッド 2 が最初に run に入った場合、それは sub() を呼び出し、スレッド 1 は決して sum() を呼び出しません。Thread2 が sum() を呼び出す前にスリープし、Thread1 が Sum() に入るのに十分な時間を確保できるように、スリープ時間も追加しましたが、Thread1 は決して入りません。

    public class ExploringThreads {
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            threadexample a1 = new threadexample();
            Thread t1 = new Thread(a1, "Thread1");
            Thread t2 = new Thread(a1,"Thread2");
            t1.start();
            t2.start();
        }
    }
    class threadexample implements Runnable{
        public int a = 10;
        public void run(){
            if(Thread.currentThread().getName().equals("Thread1"))
                sum();
            else if(Thread.currentThread().getName().equals("Thread2"))
                sub();
        }

        public synchronized void sum()
        {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"In Sum");
            sub();
        }

        public synchronized void sub()
        {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"In Sub");
            sum();
        }
    }
4

3 に答える 3

1

これは、デッドロックを取得する方法ではありません。実際、このコードはかなり安全に思えます :-) 「これ」で同期する synchronized を使用しているため、一度に 1 つのスレッドのみが sum/sub に入ります。「this」は 1 つしかないため、両方のスレッドが同じロックを取得しようとします。

たとえば、スレッド 1 に 1 つのロックがあり、スレッド 2 に 2 番目のロックがあり、スレッド 1 がロックを保持したままスレッド 2 のロックを取得し、スレッド 2 がロックを保持したままスレッド 1 のロックを取得しようとすると、デッドロックが発生します。

あなたができることは次のとおりです。

a)「threadexample」クラスでロックするための2つのオブジェクトを追加します(慣例により、クラスは大文字で始まる必要があります):

private final Object sumLock = new Object();
private final Object subLock = new Object();

b) sum/sub メソッドの両方で「synchronized」キーワードを削除し、代わりにそれぞれで synchronized() {} ブロックを使用します。合計は同期化されます(sumLock) { /* 合計の本文はここに入ります/ } サブは同期化されます(subLock) { /サブの本文はここに入ります */}。

この場合、Thread1 は sum() に入り、sumLock を取得して待機します。Thread2 は sub() に入り、subLock() を取得して待機します。Thread1 はウェイクアップし、sub() に入り、subLock を取得しようとしますが、Thread2 によって保持されているため、Thread2 が解放するまで待機します。その時点で、Thread2 はウェイクアップし、sum() に入り、Thread1 によって保持されている sumLock を取得しようとするため、Thread2 は Thread1 がそれ​​を解放するのを待ちます。

それぞれのスレッドが他のスレッドを待っているため、どちらのスレッドも先に進みません。デッドロックが発生します。

@Edit: はい、「threadexample」のインスタンスは 1 つしかなく、Thread1 と Thread2 の両方がロックを求めて戦っていますが、そのうちの 1 つがロックを取得すると、sum/sub または sub/sum を実行した後に解放されます。たとえば、Thread1 が最初で、sum() の実行を開始するとします。ロック付きです。その場合、スレッド 2 はスレッド 1 と同じロックによって保護されているため、sub() に入りません。Thread1 は sum() を実行し、次に sub() を実行してからロックを解放します --> Thread2 は sub() などに移動します。

于 2013-10-20T03:43:19.287 に答える