0

次のコードを使用してデッドロックを再現できません

次のコードを使用してデッドロックを取得しようとしていますが、うまく機能しているようです。

下記を参照してください:

public class Deadlock {

    static Object lock1 = new Object();
    static Object lock2 = new Object();

    public static void main(String[] args) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    synchronized (lock1) {
                        System.out.println("Thread 1: locked lock1");
                    }
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (lock2) {
                        System.out.println("Thread 1: locked lock2");
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    synchronized (lock2) {
                        System.out.println("Thread 2: locked lock2");
                    }
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (lock1) {
                        System.out.println("Thread 2: locked lock1");
                    }
                }
            }
        }).start();

    }

}

この場合、理解できないこと、またはこのコードの何が問題なのですか?

4

6 に答える 6

2

デッドロックを引き起こすには、これらのスレッドで両方のロックを逆の順序で保持する必要があります。

// thread 1
public void run() {
    synchronized (lock1) {
        synchronized (lock2) {
            // do something
        }
    }
}

// thread 2
public void run() {
    synchronized (lock2) {
        synchronized (lock1) {
            // do something
        }
    }
}

これは必要ですが、十分ではありません。デッドロックをシミュレートできるようにするには、両方のスレッドが最初のロックをそれぞれ正常に取得してから、次のロックを取得しようとする必要があります。

于 2012-10-29T22:44:41.880 に答える
1

デッドロックを取得しようとしている場合は、同期されたブロックをネストして、両方のロックを同時に解除しようとする必要があります。

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    synchronized (lock1) {
                        System.out.println("Thread 1: locked lock1");
                        try {
                            // Sleep to allow Thread2 to obtain lock2
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        synchronized (lock2) {
                            System.out.println("Thread 1: locked lock2");
                        }
                    }
                }
            }
        }).start();

        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        // Sleep to allow Thread1 to obtain lock1
                        Thread.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (lock2) {
                        System.out.println("Thread 2: locked lock2");
                        synchronized (lock1) {
                            System.out.println("Thread 2: locked lock1");
                        }
                    }
                }
            }
        }).start();

ロックは逆の順序で取得され、スリープは次の取得順序を保証することに注意してください。

Thread 1 acquires lock1
Thread 2 acquires lock2
Thread 1 attempts to acquire lock2       <--- DEADLOCK
Thread 2 attempts to acquire lock1       <--- DEADLOCK

最後の2つはどちらの順序でも発生する可能性がありますが、デッドロックは関係なく発生することに注意してください。

于 2012-10-29T22:46:23.370 に答える
1

上記のコードがデッドロックを引き起こすのはなぜですか?各スレッドは一度に1つのロックのみをロックするため、他のスレッドがロックしようとした場合、最初のスレッドがロックを解放するのを待つ必要があります。

スレッドがデッドロックした場合、デッドロックの深刻なリスクがあります

synchronized (lock1) {
    synchronized (lock2) {
        ...
    }
}

synchronized (lock2) {
    synchronized (lock1) {
        ...
    }
}
于 2012-10-29T22:46:44.597 に答える
1

コードが「デッドロック」することはありません。

デッドロックするには、ロック内で他のロックをロックする必要があります。

于 2012-10-29T22:44:45.100 に答える
1

デッドロックを取得するには、一度に 2 つのロックを保持する必要があります。ループ全体で最初のロックを保持できます。

于 2012-10-29T22:45:04.067 に答える
0

2 番目のスレッドで lock1 のロックを取得しようとします。これは、デッドロックを引き起こす古典的な方法です。2 つのリソースが異なる順序でロックされています。

申し訳ありません...コードを十分に下にスクロールしませんでした...愚かな気分

于 2012-10-29T22:44:31.590 に答える