2010-11-14 71 views
2

我正在實施一些簡單的生產者/消費者程序,有一些信號量和共享內存。爲了簡單起見,我們假設我的程序中只有一塊共享內存和一個信號量。什麼來鎖定和什麼不鎖定在多線程環境(信號量和共享內存)

起初,我雖然只是考慮了試圖寫入共享內存塊的代碼的關鍵部分。但是,由於共享內存塊由1024bytes組成,我不能同時讀取所有數據(這不是一個原子操作),所以當我讀它時,確實有可能生產者開始寫入,所以讀者將獲得一半的舊數據,一半新數據。由此,我只能認爲我還必須將共享內存讀取邏輯放在「信號量」塊中。

現在,我有很多的代碼看起來像這樣:

if (sharedMemory[0] == '0') { ... } 

在這種情況下,我只是希望在內存中的單個字符。我想我不必擔心在這附近放置一個信號燈,對吧?

而且如果不是我有類似

if (sharedMemory[0] == '0' && sharedMemory[1] == '1') { ... } 

從我的角度來看,我猜測,因爲這是2點的操作,我不得不認爲這是一個重要的部分,因此不必把一個什麼信號周圍。我對嗎?

謝謝!

回答

1

從技術上講,在多核或多處理器系統中,唯一的原子是彙編操作碼,它們被明確記錄爲原子。即使讀取單個字節也會給另一個處理器帶來(非常小的)機會,並在讀取它之前對其進行修改,除非在某些情況下處理CPU緩存和對齊的內存塊(有趣的線程:http://software.intel.com/en-us/forums/showthread.php?t=76744,有趣的閱讀:http://www.corensic.com/CorensicBlog/tabid/101/EntryId/8/Memory-Consistency-Models.aspx

您必須使用內部保證原子性的類型或專門保護多線程多核系統上的訪問。

(答案可能會略有上IL平臺,如.NET和JVM上,因爲他們對什麼是原子,哪些不是自己的擔保發生變化)。

+0

所以,我沒有得到你的文章的結論是什麼?我應該鎖定一切嗎? – 2010-11-14 16:51:22

+0

記錄爲原子的函數當然是原子的(假設它們不是越野車)。 – 2010-11-14 18:14:19

1

絕對鎖定在非原子操作,並檢查兩個不同的值計爲非原子操作,雖然有一些技巧可用於檢查最多四個字節或更多,前提是您的處理器不緩存結果。你必須考慮你的數據是如何使用的。但基本上,任何對共享內存的訪問都應該有一個圍繞它的信號。