臨界區(qū):訪問和操作共享數(shù)據(jù)的代碼段
如果兩個執(zhí)行線程有可能處于同一個臨界區(qū)中同時執(zhí)行,那么就稱其為競爭條件
避免并發(fā)和防止競爭條件稱為同步。
加鎖
鎖是采用原子操作實現(xiàn)的,而原子操作不存在競爭。
造成并發(fā)執(zhí)行的原因:
- 用戶空間:
- 用戶程序會被調度程序搶占和重新調度
- 信號處理是異步發(fā)生的
- 內核空間:
- 中斷
- 軟中斷和tasklet
- 內核搶占
- 睡眠及與用戶空間的同步
- 對稱多處理
真正用鎖來保護共享資源并不困難,但辨認真正需要共享的數(shù)據(jù)和相應的臨界區(qū),才是真正有挑戰(zhàn)的地方。因此,在編碼的開始階段就要設計恰當?shù)逆i。大多數(shù)內核數(shù)據(jù)結構都需要加鎖。如果有其他執(zhí)行線程可以訪問數(shù)據(jù),那么就給這些數(shù)據(jù)加上某種形式的鎖;如果任何其他什么東西都能看到數(shù)據(jù),那么就要鎖住它。注意:要給數(shù)據(jù)而不是代碼加鎖。
- 中斷安全代碼:在中斷處理程序中能避免并發(fā)訪問的安全代碼
- SMP安全代碼:在對稱多處理的機器中能避免并發(fā)訪問的安全代碼
- 搶占安全代碼:在內核搶占時能避免并發(fā)訪問的安全代碼
死鎖
死鎖的產生需要一定條件:要有一個或多個執(zhí)行線程和一個或多個資源,每個線程都在等待其中一個資源,但所有資源都已經被占用了。所有線程都在互相等待,但永遠不會釋放已經占有的資源。于是所有線程都無法繼續(xù),發(fā)生了死鎖。
避免死鎖的一些簡單規(guī)則:
- 按順序加鎖
- 防止發(fā)生饑餓
- 不要重復請求同一個鎖
- 設計應力求簡單
爭用和擴展性
加鎖粒度用來描述加鎖保護的數(shù)據(jù)規(guī)模。
鎖的爭用(lock contention),簡稱爭用,是指當鎖正在被占用時,有其他線程試圖獲得該鎖。
當鎖爭用嚴重時,加鎖太粗會降低可擴展性;而鎖爭用不明顯時,加鎖過細會加大系統(tǒng)開銷,帶來浪費。這兩種情況都會造成系統(tǒng)性能下降。