一、定義:
1、死鎖:是指兩個或兩個以上的進程(或線程)在執行過程中,因爭奪資源而造成的一種互相等待的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死鎖狀態或系統產生了死鎖,這些永遠在互相等待的進程稱為死鎖進程。
死鎖發生的四個條件
(1)互斥條件:線程對資源的訪問是排他性的,如果一個線程對占用了某資源,那么其他線程必須處於等待狀態,直到資源被釋放。
(2)請求和保持條件:線程T1至少已經保持了一個資源R1占用,但又提出對另一個資源R2請求,而此時,資源R2被其他線程T2占用,於是該線程T1也必須等待,但又對自己保持的資源R1不釋放。
(3)不剝奪條件:線程已獲得的資源,在未使用完之前,不能被其他線程剝奪,只能在使用完以后由自己釋放。
(4)環路等待條件:在死鎖發生時,必然存在一個“進程-資源環形鏈”,即:{p0,p1,p2,...pn},進程p0(或線程)等待p1占用的資源,p1等待p2占用的資源,pn等待p0占用的資源。(最直觀的理解是,p0等待p1占用的資源,而p1而在等待p0占用的資源,於是兩個進程就相互等待)
2、活鎖:是指線程1可以使用資源,但它很禮貌,讓其他線程先使用資源,線程2也可以使用資源,但它很紳士,也讓其他線程先使用資源。這樣你讓我,我讓你,最后兩個線程都無法使用資源。活鎖不會被阻塞,而是不停檢測一個永遠不可能為真的條件。除去進程本身持有的資源外,活鎖狀態的進程會持續耗費寶貴的CPU時間。
3、飢餓:是指如果線程T1占用了資源R,線程T2又請求封鎖R,於是T2等待。T3也請求資源R,當T1釋放了R上的封鎖后,系統首先批准了T3的請求,T2仍然等待。然后T4又請求封鎖R,當T3釋放了R上的封鎖之后,系統又批准了T4的請求......,T2可能永遠等待。
這也就是ReentrantLock顯示鎖里提供的不公平鎖機制(當然了,ReentrantLock也提供了公平鎖的機制,由用戶根據具體的使用場景而決定到底使用哪種鎖策略),不公平鎖能夠提高吞吐量但不可避免的會造成某些線程的飢餓。
二、區別:
1、活鎖與死鎖的區別:活鎖和死鎖類似,不同之處在於處於活鎖的線程或進程的狀態是一直在不斷改變的,活鎖不會被阻塞,而是不停檢測一個永遠不可能為真的條件。除去進程本身持有的資源外,活鎖狀態的進程會持續耗費寶貴的CPU時間。活鎖可以認為是一種特殊的飢餓。一個現實的活鎖例子是兩個 人在狹小的走廊碰到,兩個人都試着避讓對方好讓彼此通過,但是因為避讓的方向都一樣導致最后誰都不能通過走廊。簡單的說就是,活鎖和死鎖的主要區別是前者 進程的狀態可以改變但是卻不能繼續執行。
2、死鎖活鎖與飢餓的區別:進程會處於飢餓狀態是因為持續地有其它優先級更高的進程請求相同的資源。不像死鎖或者活鎖,飢餓能夠被解開。例如,當其它高優先級的進程都終止時並且沒有更高優先級的進程到達。