【code】競爭條件(race condition)

 

在一些操作系統中,協作的進程可能共享一些彼此都能讀寫的公用存儲區。這個公用存儲區可能在內存中(可能是在內核數據結構中),也可能是一個共享文件。這裏共享存儲區的位置並不影響通信的本質及其帶來的問題。爲了理解實際中進程間通信如何工作,我們考慮一個簡單但很普遍的例子:一個假脫機打印程序。當一個進程需要打印一個文件時,它將文件名放在一個特殊的假脫機目錄 (spooler directory)下。另一個進程(打印機守護進程)則週期性地檢查是否有文件需要打印,若有就打印並將該文件名從目錄下刪掉。

設想假脫機目錄中有許多槽位,編號依次爲0,1,2,…,每個槽位存放一個文件名。同時假設有兩個共享變量:out,指向下一個要打印的文件;in,指向目錄中下一個空閒槽位。可以把這兩個變量保存在一個所有進程都能訪問的文件中,該文件的長度爲兩個字。在某一時刻,0號至3號槽位空(其中的文件已經打印完畢),4號至6號槽位被佔用(其中存有排好隊列的要打印的文件名)。幾乎在同一時刻,進程A和進程B都決定將一個文件排隊打印,這種情況如圖2-21所示。

在Murphy法則(任何可能出錯的地方終將出錯)生效時,可能發生以下的情況。進程A讀到in的值爲7,將7存在一個局部變量next_free_slot中。此時發生一次時鐘中斷,CPU認爲進程A已運行了足夠長的時間,決定切換到進程B。進程B也讀取in,同樣得到值爲7,於是將7存在B的局部變量next_free_slot中。在這一時刻兩個進程都認爲下一個可用槽位是7。

進程B現在繼續運行,它將其文件名存在槽位7中並將in的值更新爲8。然後它離開,繼續執行其他操作。

最後進程A接着從上次中斷的地方再次運行。它檢查變量next_free_slot,發現其值爲7,於是將打印文件名存入7號槽位,這樣就把進程B存在那裏的文件名覆蓋掉。然後它將next_free_slot加1,得到值爲8,就將8存到in中。此時,假脫機目錄內部是一致的,所以打印機守護進程發現不了任何錯誤,但進程B卻永遠得不到任何打印輸出。類似這樣的情況,即兩個或多個進程讀寫某些共享數據,而最後的結果取決於進程運行的精確時序,稱爲競爭條件(race condition)。調試包含有競爭條件的程序是一件很頭痛的事。大多數的測試運行結果都很好,但在極少數情況下會發生一些無法解釋的奇怪現象。

7

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章