Vermeidung Deadlock-Beispiel
Frage ich mich, was sind die alternativen Möglichkeiten zur Vermeidung von Deadlocks in dem folgenden Beispiel. Das folgende Beispiel ist eine typische bank-Konto übertragen deadlock-problem. Was sind einige bessere Ansätze, es zu lösen in der Praxis ?
class Account {
double balance;
int id;
public Account(int id, double balance){
this.balance = balance;
this.id = id;
}
void withdraw(double amount){
balance -= amount;
}
void deposit(double amount){
balance += amount;
}
}
class Main{
public static void main(String [] args){
final Account a = new Account(1,1000);
final Account b = new Account(2,300);
Thread a = new Thread(){
public void run(){
transfer(a,b,200);
}
};
Thread b = new Thread(){
public void run(){
transfer(b,a,300);
}
};
a.start();
b.start();
}
public static void transfer(Account from, Account to, double amount){
synchronized(from){
synchronized(to){
from.withdraw(amount);
to.deposit(amount);
}
}
}
}
Frage ich mich, wird es lösen die deadlock-Problem, wenn ich trennen Sie das verschachtelte sperren in meiner transfer-Methode wie im folgenden
synchronized(from){
from.withdraw(amount);
}
synchronized(to){
to.deposit(amount);
}
- Dein Beispiel ist nicht klassische deadlock-Beispiel. Es immer Schloss sowohl das Konto für den gleichen thread, so dass kein deadlock auftreten wird. Wollten Sie diesen code in Ihre transfer-Methode : static void überweisen(Konto von, Konto nach, double Betrag) { synchronized(from) { aus.abheben(Betrag); synchronized(to) { to.Kaution(Betrag); } } }
Du musst angemeldet sein, um einen Kommentar abzugeben.
Art der Konten. Die dead lock ist über die Reihenfolge der Konten (a,b vs b,a).
So versuchen:
Dies ist eine klassische Frage. Ich sehe zwei mögliche Lösungen:
Diese Methode, die in der Bibel erwähnt, Parallelität in Java Parallelität in der Praxis in Kapitel 10. In diesem Buch Autoren verwenden Sie die system-hash-code der Unterscheidung der Konten. Sehen java.lang.System#identityHashCode.
Neben der Lösung der Sperre angeordnet, Sie können auch vermeiden, die deadlock durch Synchronisierung auf ein private static final lock-Objekt vor der Ausführung jedes Konto überträgt.
Diese Lösung hat das problem, dass eine private, statische lock beschränkt das system zu leistenden transfers "sequenziell".
Kann eine andere sein, wenn jedes Konto hat ein ReentrantLock:
Deadlock nicht auftreten, in diesem Ansatz, weil diese sperren werden nie auf unbestimmte Zeit festgehalten. Wenn das aktuelle Objekt Sperre erworben, aber die zweite Sperre nicht verfügbar ist, wird der erste lock wird freigegeben, und der thread schläft für einige angegebene Zeit, bevor Sie versuchen, erneut das lock.
Können Sie auch erstellen Sie separate Sperre für jedes Konto (im Konto-Klasse) und dann vor der Transaktion erwerben die beiden Schlösser. Werfen Sie einen Blick:
Nach zwei sperren, die Sie tun können, zu übertragen, ohne sich Gedanken über die sichere.
Hier ist die Lösung für das problem angegeben.
Gibt es drei Voraussetzungen müssen Sie erfüllen:
Können Sie erreichen 1. und 2. durch die Verwendung Atomics, aber Sie haben etwas anderes, dass
double
da es keineAtomicDouble
.AtomicLong
würde wahrscheinlich Ihre beste Wette.Also du bist Links mit Ihrem Dritten Voraussetzung - gelingt es, die anderen muss gelingen. Es ist eine einfache Technik, die funktioniert hervorragend mit atomics und das ist mit der
getAndAdd
Methoden.Account.credit/debit
werfen, wenn etwas OP herum zu dass.