Advanced Java Services | DeadLock Beispiele |
Dieses Beispiel arbeitet mit synchronized-Blöcken und zwei Objekten, die als Lock dienen. der erste Thread holt sich einen ersten Lock, wartet und will sich dann den zweiten Lock holen. In der Wartezeit hat sich aber der andere Thread den zweiten Lock geholt und will den ersten. Nun sind die Threads blockiert. Der Einfachheit halber werden statische innere Klassen verwendet.
public class DeadLockDemo01 { public static Object lock1 = new Object(); public static Object lock2 = new Object(); public static void main(String[] a) { Thread thread1 = new Thread1("thread 1"); Thread thread2 = new Thread2("thread 2"); thread1.start(); thread2.start(); } private static class Thread1 extends Thread { public Thread1(String name) { this.setName(name); } public void run() { synchronized(lock1) { System.out.println(this.getName() + " holds lock on lock1"); Be.idleFor(10); System.out.println(this.getName() + " waiting for lock on lock2"); synchronized(lock2) { System.out.println(this.getName() + " holds lock on lock2"); } } } } private static class Thread2 extends Thread { public Thread2(String name) { this.setName(name); } public void run() { synchronized(lock2) { System.out.println(this.getName() + " holds lock on lock2"); Be.idleFor(10); System.out.println(this.getName() + " waiting for lock on lock1"); synchronized(lock1) { System.out.println(this.getName() + " holds lock on lock1"); } } } } private static class Be { public static void idleFor(int millis) { try { Thread.currentThread().sleep(millis); } catch(InterruptedException ex) { // TODO Auto-generated catch block ex.printStackTrace(); } } } }
Startet man dieses Beispiel über die Konsole, so erhält man eine vierzeilige Ausgabe und dann tritt der Deadlock ein. Wenn man jetzt Ctrl Break (Windows) bzw. Ctrl \ (Unix, Solaris) eingibt, erhält man folgende Meldungen.
Im zweiten Beispiel wird die Klasse java.util.concurrent.locks.ReentrantLock verwendet. Der Aufbau des Programms ist wie in Beispiel 1.
public class DeadLock02 { public static Lock lock1 = new ReentrantLock(); public static Lock lock2 = new ReentrantLock(); public static void main(String[] a) { Thread thread1 = new Thread1("thread 1"); Thread thread2 = new Thread2("thread 2"); thread1.start(); thread2.start(); } private static class Thread1 extends Thread { public Thread1(String name) { this.setName(name); } public void run() { try { lock1.lock(); System.out.println(this.getName() + " holds lock on lock1"); Be.idleFor(10); System.out.println(this.getName() + " waiting for lock on lock2"); try { lock2.lock(); System.out.println(this.getName() + " holds lock on lock2"); } finally { lock2.unlock(); } } finally { lock1.unlock(); } } } private static class Thread2 extends Thread { public Thread2(String name) { this.setName(name); } public void run() { try { lock2.lock(); System.out.println(this.getName() + " holds lock on lock2"); Be.idleFor(10); System.out.println(this.getName() + " waiting for lock on lock1"); try { lock1.lock(); System.out.println(this.getName() + " holds lock on lock1"); } finally { lock1.unlock(); } } finally { lock2.unlock(); } } } private static class Be { public static void idleFor(int millis) { try { Thread.currentThread().sleep(millis); } catch(InterruptedException ex) { // TODO Auto-generated catch block ex.printStackTrace(); } } } }
Startet man dieses Beispiel über die Konsole, so erhält man eine vierzeilige Ausgabe und dann tritt der Deadlock ein. Wenn man jetzt Ctrl Break (Windows) bzw. Ctrl \ (Unix, Solaris) eingibt, erhält man folgende Meldungen.