在介紹臨界區互斥問題的時候,提到了忙等待和讓權等待的概念。
在解決臨界區互斥問題的硬件解決方案中有一種利用TSL指令實現互斥的方案,里面提到了加鎖的概念,查閱資料發現加鎖有自旋鎖和互斥鎖兩種。
首先,什么是忙等待?什么是讓權等待?
忙等待:可以與自旋鎖、輪詢等同,進程不斷申請進入臨界區,直到被允許。像 while(judge)
讓權等待:進程申請進入臨界區,不被允許則睡眠(阻塞、等待)。像 sleep()
睡眠是阻塞的一種方式,睡眠的進程會sleep一段時間,醒來后繼續運行。
兩者比較,忙等待一直占用CPU,一直申請進入臨界區操作,進程處於運行態;
讓權等待申請一次后被拒,則主動讓出CPU,進程處於阻塞態
那么,什么是自旋鎖?什么是互斥鎖?
鎖:指進入臨界區的判斷標志,
比如變量LOCK,若LOCK=0,表示當前臨界區無進程,申請的進程可以進入,若LOCK=1,表示當前臨界區有進程,申請的進程都不允許進入
自旋鎖:代碼說明:while(LOCK==1); LOCK=1;(只是簡單地說明意思,並不一定是這樣的)
實際上,自旋鎖是硬件實現的,會“鎖總線”,將這兩行代碼變成一個原子操作(命令TSL或XCHG),以保證不會被中斷,實現互斥。
互斥鎖:代碼說明:while(LOCK==1) {sleep; } LOCK=1;(只是簡單地說明意思,並不一定是這樣的)
同上,硬件實現,原子操作
兩者比較,使用自旋鎖會導致忙等待,使用互斥鎖會導致進程讓權等待
自旋鎖的忙等會浪費CPU,長時間的浪費可能導致死鎖。
所以,自旋鎖適用於臨界區操作時間短的多進程,操作時間短可以減少忙等的時間。
而互斥鎖由於需要進程調度且睡眠時間較長,所以適用於臨界區操作時間長的。
另外,自旋鎖只適用於多處理器的情況,在單處理器中相當於空操作。why?
如果是單處理器,
對於非搶占式(沒有時間片,只有結束或者阻塞的時候,才會釋放CPU,讓其他進程運行),
不會發生一個獲得鎖的進程被迫釋放CPU的情況,所以進程會按照優先級完成臨界區的操作,終止進程,讓出CPU給下個進程。這種情況下,沒有自旋的發生,自旋鎖也就沒用了。
對於搶占式(沒有時間片,在運行過程中,會被高優先級的進程搶占CPU),
會發生一個獲得鎖的進程被搶占被迫釋放CPU的情況,如果發生搶占,臨界區的鎖還在被搶占的進程手里,搶占CPU的進程沒有獲得鎖,只能一直自旋,形成死鎖。(所以自旋鎖都設置了自旋時間的上限,以防止這種情況的發生)
為了應對搶占式可能形成死鎖的情況,對自旋鎖進行優化,使得單處理器的自旋鎖可以禁止進程搶占,將搶占式變成非搶占式,而非搶占式又沒有自旋,所以單處理器的自旋相當於空操作
參考
https://blog.csdn.net/liuchuo/article/details/51986201/