Java-Thread-Deadlock und seine Lösung

Um den Thread-Deadlock zu verstehen, müssen wir zuerst verstehen, was ein Deadlock ist

 

Sackgasse

In Laienbegriffen: Deadlock ist ein Blockierungsphänomen, das durch den Wettbewerb um Ressourcen oder durch die Kommunikation zwischen zwei oder mehr Prozessen oder Threads während der Ausführung verursacht wird. Wenn keine externe Kraft vorhanden ist, können sie nicht vorrücken.

 

Verwenden wir ein einfacheres Beispiel

 

In diesem Beispiel für einen Stau ist beispielsweise aus der Abbildung ersichtlich, dass sich in vier Richtungen fahrende Autos gegenseitig blockieren. Wenn in keiner Richtung ein Auto zurückkehrt, wird ein Deadlock gebildet.

In der obigen Abbildung gibt es vier Gründe für einen Deadlock:

1. Sich gegenseitig ausschließende Bedingungen: Eine Ressource kann jeweils nur von einem Thread verwendet werden. Jede Straße auf der Karte kann nur Autos in eine Richtung passieren lassen, sodass eine der Bedingungen für einen Deadlock erfüllt ist

2. Anforderungs- und Haltebedingungen: Wenn ein Prozess durch Anfordern von Ressourcen blockiert wird, werden die erfassten Ressourcen weiterhin gehalten. Es ist zu sehen, dass Autos in jeder Richtung auf der Karte darauf warten, dass Autos in anderen Richtungen evakuiert werden, sodass die zweite Bedingung für einen Deadlock erfüllt ist.

3. Bedingungen ohne Entzug: Die durch den Prozess gewonnenen Ressourcen können nicht gewaltsam entzogen werden, bevor sie aufgebraucht sind. Es wird hier davon ausgegangen, dass es keine Verkehrspolizei gibt, dann kann niemand die Evakuierung von Autos in andere Richtungen mit Gewalt beantragen, so dass die dritte Bedingung des Deadlocks erfüllt ist

4. Zyklische Wartebedingung: Eine Art zyklische Warte-Ressourcenbeziehung wird zwischen mehreren Prozessen oder Threads gebildet. Dies wird in der Figur sehr intuitiv ausgedrückt
 

 

Deadlock Java Code kleines Beispiel

 

 

 

package huaxin2016_9_9;

public class ThreadDeadlock {
	public static void main(String[] args) throws InterruptedException {
		Object obj1 = new Object();
		Object obj2 = new Object();
		Object obj3 = new Object(); 
		//新建三个线程
		Thread t1 = new Thread(new SyncThread(obj1, obj2), "t1"); 
		Thread t2 = new Thread(new SyncThread(obj2, obj3), "t2"); 
		Thread t3 = new Thread(new SyncThread(obj3, obj1), "t3"); 
		//让线程依次开始
		t1.start(); 
		//让线程休眠
		Thread.sleep(5000);
		t2.start();
		Thread.sleep(5000);
		t3.start();
	} 
} 
class SyncThread implements Runnable{ 
	private Object obj1; 
	private Object obj2;
	//构造函数
	public SyncThread(Object o1, Object o2){ 
		this.obj1=o1;
		this.obj2=o2;
	} 
	@Override
	public void run() {
		//获取并当前运行线程的名称
		String name = Thread.currentThread().getName();
		System.out.println(name + " acquiring lock on "+obj1);
		
		
		synchronized (obj1) { 
			System.out.println(name + " acquired lock on "+obj1); 
			work();
			System.out.println(name + " acquiring lock on "+obj2); 
			synchronized (obj2) { 
				System.out.println(name + " acquired lock on "+obj2); 
				work();
		    } 
			System.out.println(name + " released lock on "+obj2); 
	    } 
		System.out.println(name + " released lock on "+obj1); 
		System.out.println(name + " finished execution.");
	}
	private void work() { 
		try { 
			Thread.sleep(30000); 
		} 
		catch (InterruptedException e) { 
			e.printStackTrace();
		}
	} 
}

Das Ergebnis des obigen Deadlock-Beispiels ist

 

 

t1 acquiring lock on java.lang.Object@675d5ed4
t1 acquired lock on java.lang.Object@675d5ed4
t2 acquiring lock on java.lang.Object@7943f708
t2 acquired lock on java.lang.Object@7943f708
t3 acquiring lock on java.lang.Object@46767615
t3 acquired lock on java.lang.Object@46767615
t1 acquiring lock on java.lang.Object@7943f708
t2 acquiring lock on java.lang.Object@46767615
t3 acquiring lock on java.lang.Object@675d5ed4

Es ist intuitiv zu erkennen, dass t1, t2 und t3 alle Ressourcen anfordern, aber alle ihre eigenen Ressourcen verwalten, was zu einem Deadlock führt.

 

 

Lösung:

1. Um die sich gegenseitig ausschließende Bedingung zu brechen, müssen wir dem Prozess erlauben, gleichzeitig auf bestimmte Ressourcen zuzugreifen. Diese Methode unterliegt dem tatsächlichen Szenario und es ist nicht einfach, die Bedingung zu erreichen.

2. Brechen Sie die Nicht-Vorkaufsbedingung. Auf diese Weise müssen Sie dem Prozess erlauben, bestimmte Ressourcen zwangsweise vom Insassen zu beschlagnahmen, oder einfach verstehen, dass der Prozess, der die Ressource belegt, nicht mehr für die Belegung anderer Ressourcen gelten kann Die Anwendung muss nach den vorhandenen Ressourcen freigegeben werden. Dies ist tatsächlich schwierig. Es ist auch schwierig, geeignete Szenarien zu finden.

3. Der Prozess gilt für alle Ressourcen, bevor er ausgeführt wird. Andernfalls kann der Prozess nicht in den ausführbaren Zustand versetzt werden. Diese Methode scheint nützlich zu sein, hat jedoch den Nachteil, dass sie zu einer verringerten Ressourcennutzung und Prozessgleichzeitigkeit führen kann

4. Vermeiden Sie Ressourcenanwendungsschleifen, dh sortieren und nummerieren Sie Ressourcen im Voraus und weisen Sie sie nach Anzahl zu. Diese Methode kann die Ressourcennutzung und den Systemdurchsatz effektiv verbessern, erhöht jedoch den Systemaufwand und die Zeit, in der der Prozess Ressourcen beansprucht.

 

(1) Die einfachste und am häufigsten verwendete Methode ist der Neustart des Systems. Diese Methode ist jedoch sehr kostspielig. Dies bedeutet, dass alle durch den Prozess abgeschlossenen Berechnungsarbeiten, einschließlich der Teilnahme am Tod, verschwendet werden gesperrt und Prozesse, die nicht am Deadlock beteiligt sind

(2). Brechen Sie den Prozess ab und entziehen Sie Ressourcen. Beenden Sie die am Deadlock beteiligten Prozesse und stellen Sie die von ihnen belegten Ressourcen wieder her, um den Deadlock zu beseitigen. Zu diesem Zeitpunkt gibt es zwei Situationen: Alle gleichzeitig am Deadlock beteiligten Prozesse abbrechen und alle Ressourcen entziehen oder die am Deadlock beteiligten Prozesse schrittweise abbrechen und die vom Deadlock-Prozess belegten Ressourcen schrittweise wiederherstellen. Im Allgemeinen müssen Sie bei der Auswahl eines Prozesses, der schrittweise abgebrochen werden soll, bestimmte Grundsätze befolgen. Der Zweck besteht darin, den Prozess mit den geringsten Kosten abzubrechen, z Der Prozess, wenn er ausgeführt wird, und der externe Prozess beziehen sich auf den Prozess. Faktoren wie die Kosten des Jobs

(3). Prozess-Rollback-Strategie, dh, der am Deadlock beteiligte Prozess wird bis zu einem Punkt vor dem Deadlock zurückgesetzt Setzen Sie die Ausführung an dieser Stelle fort, damit es nicht wieder zu Deadlock kommt. Obwohl dies eine ideale Methode ist, ist der Betrieb extrem teuer. Es ist ein Mechanismus wie ein Stapel erforderlich, um jede Änderung des Prozesses für zukünftige Rollbacks aufzuzeichnen. Manchmal ist dies nicht möglich.

 

 

 

Ich denke du magst

Origin blog.csdn.net/dream_18/article/details/52644903
Empfohlen
Rangfolge