行程同步與臨界區間問題

互斥(mutual exclusion)

互斥是三項臨界區間要求中最簡單、也最重要的一項:對於某一份共用資料,任一時刻最多只能有一條執行緒待在臨界區間裡。之所以叫「互」斥,是因為執行緒們彼此排除——我在裡面,你就被擋在外面,反之亦然。單人廁所就是最完美的寫照:那把鎖保證裡頭的人完全獨享,其他所有人都得排隊等。

互斥是直接擊敗競爭條件的那項性質。回想一下,競爭之所以發生,是因為兩條執行緒對共用資料的多步驟操作交錯了。如果在做那些步驟的臨界區間上互斥成立,這些步驟就無法交錯:執行緒 A 必須完整做完它的讀取、相加、寫回,才輪到執行緒 B 開始,於是沒有更新會被丟失。實際上,互斥把一段非原子的區域變成了實質原子的區域。提供互斥的機制,從巧妙的純軟體協定(皮特森解法)一路到硬體原子指令、互斥鎖、號誌都有;它們在成本與便利性上不同,卻都承諾同一個「一次一個」的保證。

兩點誠實的提醒。第一,互斥是安全性而非活性:它本身完全沒說等待中的執行緒究竟進不進得去,所以一個互斥的機制仍可能死結或餓死某人——這正是為什麼進展與有限等待是分開的另兩項要求。第二,互斥不是免費的,也並非永遠值得追求。當一條執行緒持有它時,其他所有需要該資源的執行緒都被阻擋,這會把程式的那一段「序列化」,限制你能得到多少平行加速;這就是為什麼好的設計會讓臨界區間保持短、只保護真正必須獨佔的部分。有時候一個唯讀的工作根本不需要互斥,或可以用較弱的機制(允許多個讀者、但只能一個寫者)。

印表機是一項必須互斥的資源:若兩個列印工作把各自的行交錯送出,你會得到一張亂掉的頁面,而不是兩張乾淨的。在「把這份文件送去列印」那段程式碼外加一把鎖,就能讓每個工作完整印完,下一個才開始。

互斥 = 任一時刻臨界區間裡最多只有一條執行緒。

互斥對正確性是必要但不充分的。它只是安全性保證;把它和其他鎖隨意搭配,正是死結產生的途徑。

又称
mutex互斥性