Problem
|
Zwei threads und zwei Resourcen,
|
|
jeder thread befindet sich in einem kritischen Abschnitt
einer Resource und möchte auf die jeweils andere Resource
zugreifen
|
Beispiel
|
class Deadlock {
Object lock1 = new SomeClass();
Object lock2 = new SomeClass();
public void foo() {
synchronized (lock1) {
synchronized (lock2) {
}
}
}
public void bar() {
synchronized (lock2) {
synchronized (lock1) {
}
}
}
}
|
| |
|
Die Erkennung von deadlocks ist nicht immmer so einfach!!!
|
2. Beispiel
|
Zyklische Struktur mit geschachtelten Monitoraufrufen
|
|
class X {
Y y1;
public
synchronized
void setY1(Y y) {
y1 = y;
}
public
synchronized
void foo() {
y1.bar();
}
public
synchronized
void bar() {
}
}
class Y {
X x1;
public
synchronized
void setX1(X x) {
x1 = x;
}
public
synchronized
void foo() {
x1.bar();
}
public
synchronized
void bar() {
}
}
public
class Deadlock2 {
X x;
Y y;
public Deadlock2() {
x = new X();
y = new Y();
x.setY1(y);
y.setX1(x);
t1 = new MyThread(x,y);
t2 = new MyThread(x,y);
t1.start();
t2.start();
}
}
|
|
Geschachtelte Monitor-Aufrufe für verschiedene Objekte bergen immer die Gefahr
von Verklemmungen.
|
|
Die Deadlock-Freiheit kann nicht durch Testen gezeigt
werden.
|
|
Die Deadlock-Freiheit kann nur durch systematische
Programm-Konstruktion erreicht werden.
|
|
|
Beispiel |
Die beiden folgenden Programmfragmente erzeugen also, wie in einer früheren Version dieser Seite
fälschlicherweise dargestellt, keinen Deadlock,
da hier der gleicheThread mehrfach einen Monitor betritt. Dieses ist explizit erlaubt.
|
|
class X {
synchronized void f() {
f();
}
}
|
oder
|
|
class X {
void f() {
synchronized (this) {
synchronized (this) {
}
}
}
}
|