為什么需要同步機(jī)制?
? ? ? 如果某一個(gè)進(jìn)程在對(duì)某個(gè)數(shù)據(jù)結(jié)構(gòu)進(jìn)行操作時(shí)被掛起,那么其他的進(jìn)程就不應(yīng)該對(duì)該數(shù)據(jù)結(jié)構(gòu)進(jìn)行操作,除非他已被重新設(shè)置成一致性狀態(tài),否則兩個(gè)進(jìn)程的交互作用,將破壞所存儲(chǔ)的信息。這個(gè)同步問(wèn)題不僅出現(xiàn)在共享公共數(shù)據(jù)的進(jìn)程之間,也出現(xiàn)在內(nèi)核的控制路徑之間。
? ? ? 在開始同步方法的說(shuō)明之前,首先來(lái)明確兩個(gè)概念。
何謂臨界區(qū)?
? ? ? 臨界區(qū)是這樣的一段代碼:進(jìn)入這段代碼的進(jìn)程必須完成,之后另一個(gè)進(jìn)程才能進(jìn)入。
何謂內(nèi)核控制路徑?
? ? ? 內(nèi)核控制路徑表示內(nèi)核處理系統(tǒng)調(diào)用,異常和中斷所執(zhí)行的指令序列。
? ? 那么到底目前有哪一些同步機(jī)制呢?下面就開始為大家一一解答。
非搶占式內(nèi)核
在尋找徹底簡(jiǎn)單的解決同步問(wèn)題的方案中,大多數(shù)傳統(tǒng)的Unix內(nèi)核,都是非搶占式的:當(dāng)某一進(jìn)程在執(zhí)行,他不能被任意掛起,也不能被另一個(gè)進(jìn)程代替。
禁止中斷
在進(jìn)入一個(gè)臨界區(qū)之前禁止所有硬件中斷,一開始在重新啟用中斷。這種機(jī)制,盡管簡(jiǎn)單,但遠(yuǎn)不是最佳的,如果臨界區(qū)比較大,那么在一個(gè)相對(duì)較長(zhǎng)的時(shí)間內(nèi)持續(xù)禁止中斷就可能是所有的硬件活動(dòng)處于凍結(jié)狀態(tài)。
? 信號(hào)量
這是一種廣泛使用的同步機(jī)制。所謂信號(hào)量,就是與某個(gè)數(shù)據(jù)結(jié)構(gòu)相關(guān)的計(jì)數(shù)器,所有線程在試圖訪問(wèn)這個(gè)數(shù)據(jù)結(jié)構(gòu)之前都要檢查這個(gè)信號(hào)量??梢园研盘?hào)量看成一個(gè)對(duì)象,其組成如下:
1一個(gè)整數(shù)變量;
2一個(gè)等待進(jìn)程的鏈表;
3兩個(gè)原子方法,down()和up()。
每個(gè)要保護(hù)的數(shù)據(jù)結(jié)構(gòu)都有他自己的信號(hào)量(初始值為1),當(dāng)某進(jìn)程希望訪問(wèn)這個(gè)數(shù)據(jù)結(jié)構(gòu)時(shí),她在相應(yīng)的信號(hào)量上執(zhí)行down()函數(shù),如果信號(hào)量的當(dāng)前值不是負(fù)數(shù),則允許訪問(wèn)這個(gè)數(shù)據(jù)結(jié)構(gòu),否則把該進(jìn)程加入到這個(gè)信號(hào)量的鏈表并阻塞該進(jìn)程。當(dāng)另一個(gè)進(jìn)程在那個(gè)信號(hào)量上執(zhí)行up()函數(shù)時(shí),允許信號(hào)量鏈表上的下一個(gè)進(jìn)程繼續(xù)執(zhí)行。
自旋鎖
在多處理器操作系統(tǒng)中,我們建議使用自旋鎖。自旋鎖與信號(hào)量非常相似,但沒有進(jìn)程鏈表。當(dāng)一個(gè)進(jìn)程,發(fā)現(xiàn)鎖被另一個(gè)進(jìn)程所著時(shí),他就不停的"旋轉(zhuǎn)",執(zhí)行一個(gè)緊湊的循環(huán)指令,直到鎖打開。 當(dāng)然是選手,在單處理器環(huán)境下是無(wú)效的,因?yàn)樗鼤?huì)造成系統(tǒng)的掛起。
避免死鎖
那么什么是死鎖呢,舉一個(gè)最簡(jiǎn)單的死鎖的例子,進(jìn)程1獲得訪問(wèn)數(shù)據(jù)結(jié)構(gòu)a的權(quán)限,進(jìn)程2獲得訪問(wèn)b的權(quán)限。但是進(jìn)程1在等待b,進(jìn)程2在等待a。進(jìn)程之間其他更復(fù)雜的循環(huán)等待的情況也可能發(fā)生。顯然死鎖情形會(huì)導(dǎo)致受影響的進(jìn)程完全處于凍結(jié)狀態(tài)。