簡單來說,死鎖就是兩個線程各自得到一個監視器的狀況下,在互相等待對方的監視器,就會發生死鎖。java
public class DeadLock { private final Object obj1 = new Object(); private final Object obj2 = new Object(); public void leftRight() throws Exception { synchronized (obj1) { Thread.sleep(500); synchronized (obj2) { System.out.println("I'm in leftRight!"); } } } public void rightLeft() throws Exception { synchronized (obj2) { Thread.sleep(500); synchronized (obj1) { System.out.println("I'm in rightLeft!"); } } } public static void main(String[] args) throws InterruptedException { DeadLock deadLock = new DeadLock(); Thread0 thread0 = new Thread0(deadLock); Thread1 thread1 = new Thread1(deadLock); thread0.start(); thread1.start(); } } class Thread0 extends Thread { private DeadLock dLock; public Thread0(DeadLock dLock) { this.dLock = dLock; } public void run() { try { dLock.leftRight(); } catch (Exception e) { e.printStackTrace(); } } } class Thread1 extends Thread { private DeadLock dLock; public Thread1(DeadLock dLock) { this.dLock = dLock; } public void run() { try { dLock.rightLeft(); } catch (Exception e) { e.printStackTrace(); } } }
運行該程序會發現,什麼結果都不會打印,由於程序死鎖了。那麼如何定位死鎖的問題呢?算法
一、使用jps得到當年java虛擬機進程的pid工具
二、使用jstack工具打印堆棧,在打印信息的最後會告訴咱們發現了一處死鎖。(本身也能夠根據打印信息分析分析)this
能夠看到,thread-1鎖住了e1cda4b0,而後想得到e1cda4a0這個監視器,而後同時thread-0鎖住了e1cda4a0,想得到e1cda4b0,因而就形成了deadlock。spa
那麼咱們該如何預防死鎖呢?線程
首先咱們要弄明白死鎖產生的條件是什麼?code
死鎖產生條件4個:互斥條件、不可搶佔條件、佔有並等待、循環等待條件。
死鎖預防:死鎖4個條件其中一個不知足就不會發生,通常從後三個入手。
破壞不可搶佔條件:當已佔有資源的線程,又要申請新的資源,但不能當即被知足時,必須釋放所佔有的所有資源,之後再從新申請。
破壞佔有並等待:實行資源預先分配策略,一次性分配資源給他,若不知足則不分配
破壞循環等待:實行資源有序分配策略,因此線程按規定順序申請資源,這樣就不會造成環路。
死鎖避免:容許前三個條件存在,經過合理的資源分配算法來確保不會造成環形等待,來避免四個條件都成立從而避免死鎖。有銀行家算法。