2015-07-22 121 views
1

考慮我們有三個線程,bool status_flag[500]陣列和工作情況如下:在這種情況下,我真的需要互斥鎖嗎?

  1. 兩個線程只有在status_flag陣列在不同的索引寫作。而第三個線程只能讀取任何索引。

  2. 所有三個線程寫在不同的索引。儘管所有三個線程都在任何索引處讀取。

在書寫操作中,我們只是設置標誌,不會重新設置它。

status_flag [i] = true; 

在讀取操作中,我們正在做這樣的事情:

for(;;){ //spinning to get flag true 
     if(status_flag [i] == true){ 
      //do_something ; 
      break; 
     } 
    } 

什麼發生,如果編譯器優化(分支預測)代碼?

我已經讀了很多關於鎖定的知識,但仍然有混淆的結論。請幫我總結一下。

+3

您需要同步。無論你需要*互斥*是一個不同的問題。 – EOF

+0

是的,互斥/信號量,操作必須是「原子的」,因爲你從另一個線程寫入的地方讀取。 –

+0

@mohan分支預測是一種處理器流水線優化。如果你認爲'status_flag'會被優化,你可以使用'volatile'關鍵字。 –

回答

2

POSIX is quite clear on this

申請應確保通過控制(線程或進程)的多於一個的線程訪問任何存儲器位置被限制,使得沒有控制線程能夠讀取或修改的存儲器位置,而另一個控制線程可能正在修改它。

因此,不鎖定您不允許讀取其他線程可能正在寫入的內存。此外,POSIX的那部分描述了哪個函數將同步線程之間的內存。在兩個線程都調用其中列出的任何函數之前,您不能保證一個線程所做的更改對另一個線程是可見的。

+0

我明白了,但在國旗的情況下仍然存在混淆。如果我正在閱讀價值沒有同步,我會得到一些垃圾或陳舊的數據。但是如果一個線程只寫入(true)標誌和其他線程讀入for循環,直到它變爲真,那該怎麼辦?沒有保證不更新數據到其他線程沒有同步? – Mohan

+0

@莫漢:POSIX很清楚,不是嗎?如果你不相信,請嘗試一下,不要同步。你會失敗,可能並不總是,但有時候。 – alk

+0

@alk它不是關於相信。我只是想知道在其他閱讀線程,它旋轉得到真正的國旗,仍然有失敗的可能性爲什麼?也許是因爲緩存或其他不允許讀取線程來獲取更新值的其他內容。我只想知道根本原因。 – Mohan

0

如果所有線程都在不同的索引值上運行,那麼您不需要鎖定。基本上它等同於使用不同的變量。 在您的代碼中,變量i的值未被設置或修改。所以它只讀取一個特定的標誌索引。而寫作你使用不同的索引,在這種情況下,不需要使用鎖定。

+0

很明顯,如果線程總是*寫入不同的索引,那麼循環將是無限的... –

+0

@Oliver Charlesworth我確定索引被讀取的時候肯定會寫入。如果它在索引(例如5)處讀取並且在它開始讀取之後在相同索引(例如5)處發生寫入。那麼線程哪個閱讀能夠打破循環?或者它仍會讀取陳舊的數據。 – Mohan

+0

@莫漢:如果你正在讀和寫相同的索引,那麼你需要一個鎖。 – Dipanjan

相關問題