私はJavaでいくつかの演習を行っています(コードがどこから来たのかと思う人もいるかもしれません)。次のコードでデッドロック状態を引き起こそうとします:
class Resource {
public Integer value = 42;
}
public class DeadLockRisk implements Runnable {
private Resource resourceA = new Resource();
private Resource resourceB = new Resource();
public void write(int a, int b) {
System.out.println(Thread.currentThread().getName() + " try write Lock A");
synchronized(resourceA) {
System.out.println(Thread.currentThread().getName() + " write Lock A");
System.out.println(Thread.currentThread().getName() + " try write Lock B");
synchronized(resourceB) {
System.out.println(Thread.currentThread().getName() + " write Lock B");
resourceA.value = a;
resourceB.value = b;
//sit on it!
//try { Thread.sleep(5000); } catch (Exception e) {}
System.out.println(Thread.currentThread().getName() + " release write B");
}
System.out.println(Thread.currentThread().getName() + " release write A");
}
}
public int read() {
Integer retVal;
System.out.println(Thread.currentThread().getName() + " try read Lock B");
synchronized(resourceB) {
System.out.println(Thread.currentThread().getName() + " read Lock B");
System.out.println(Thread.currentThread().getName() + " try read Lock A");
synchronized(resourceA) {
System.out.println(Thread.currentThread().getName() + " read Lock A");
retVal = resourceB.value + resourceA.value;
System.out.println(Thread.currentThread().getName() + " release read A");
}
System.out.println(Thread.currentThread().getName() + " release read B");
}
return retVal;
}
public void run() {
if (Thread.currentThread().getName().equals("Thread-1")) {
write(1,2);
}
System.out.println(read());
}
public static void main(String[] args) {
Thread ta = new Thread(new DeadLockRisk());
Thread tb = new Thread(new DeadLockRisk());
ta.start(); tb.start();
}
}
(javac -version javac 1.6.0_0 uname -a Linux inspiron 2.6.29 #1 SMP Sat May 16 10:56:17 CEST 2009 i686 GNU/Linux)
(他の状況の中でも)以下の出力を取得します。
スレッド 1 書き込みロック A を試行 スレッド 0 読み取りロック B を試行 スレッド 1 書き込みロック A <===== スレッド 0 読み取りロック B スレッド 1 書き込みロック B を試行 スレッド 0 読み取りロック A を試行 スレッド 1 書き込みロック B スレッド 0 読み取りロック A <===== スレッド 1 解放書き込み B スレッド 0 解放読み取り A スレッド 1 リリース書き込み A スレッド 0 解放読み取り B Thread-1 try read ロック B 154 スレッド 1 読み取りロック B Thread-1 try read ロック A スレッド 1 読み取りロック A スレッド 1 リリース読み取り A スレッド 1 リリース読み取り B 3
何が間違っていると思いますか? ロックがスレッド 1 によって解放される前に、スレッド 0 が read() のクリティカル セクションに入り、A のロックを取得する方法さえあります。出力が同期していないため、これは可能ですか? このコードではデッドロックは発生しません。