根據不少同學的面試反饋,最近阿里和字節跳動面試時都對多線程相關的問題進行了重點考察,並且面試官都問到了死鎖問題。如字節跳動考察的問題是:
- 什麼是線程死鎖?
- 死鎖如何產生?
- 如何避免線程死鎖?
01 什麼是線程死鎖
02 死鎖如何產生
# 場景一
# 場景二
# 場景三
# 場景四
public class JavaTest { @Test public void test() { final Object lockA = new Object(); final Object lockB = new Object(); new Thread(new Runnable() { @Override public void run() { synchronized (lockA) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lockB) { } System.out.println("finish A"); } } }).start(); new Thread(new Runnable() { @Override public void run() { synchronized (lockB) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (lockA) { } System.out.println("finish B"); } } }).start(); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } }}
03 如何避免線程死鎖
# 方案一
# 方案二
# 方案三
# 方案四
04 常考面試考點
加鎖順序:當多個線程需要相同的一些鎖,但是按照不同的順序加鎖,死鎖就很容易發生。如果能確保所有的線程都是按照相同的順序獲得鎖,那麼死鎖就不會發生。當然這種方式需要你事先知道所有可能會用到的鎖,然而總有些時候是無法預知的。
加鎖時限:加上一個超時時間,若一個線程沒有在給定的時限內成功獲得所有需要的鎖,則會進行回退並釋放所有已經獲得的鎖,然後等待一段隨機的時間再重試。但是如果有非常多的線程同一時間去競爭同一批資源,就算有超時和回退機制,還是可能會導致這些線程重複地嘗試但卻始終得不到鎖。
死鎖檢測:死鎖檢測即每當一個線程獲得了鎖,會在線程和鎖相關的數據結構中( map 、 graph 等)將其記下。除此之外,每當有線程請求鎖,也需要記錄在這個數據結構中。死鎖檢測是一個更好的死鎖預防機制,它主要是針對那些不可能實現按序加鎖並且鎖超時也不可行的場景。
其中,死鎖檢測最出名的算法是由艾茲格·迪傑斯特拉在 1965 年設計的銀行家算法,通過記錄系統中的資源向量、最大需求矩陣、分配矩陣、需求矩陣,以保證系統只在安全狀態下進行資源分配,由此來避免死鎖,對於面算法崗的同學一定要對其有所瞭解。
後臺回覆“加羣”,帶你進入高手如雲交流羣。如果你喜歡本文,不妨分享給你喜歡的朋友讀,或者點下右下角的“在看”,謝謝了!
推薦閱讀:
10T 技術資源大放送!包括但不限於:雲計算、虛擬化、微服務、大數據、網絡、Linux、Docker、Kubernetes、Python、Go、C/C++、Shell、PPT 等。在公衆號內回覆「1024」,即可免費獲取!!