2012-01-09 45 views
3

的問題是相當簡單的問: 如果我有是否性病::原子防止非原子變量的重新排序在原子變量

settings[N_STNGS];//used by many threads 
std::atomic<size_t> current_settings(0); 
void updateSettings()//called by single thread , always the same thread if that is important 
{ 

    auto new_settings = (current_settings+1)%N_STNGS; 
    settings[new_settings].loadFromFileSystem(); //line A 
    current_settings=new_settings; //line B 
} 

做標準保證線B線後不會重新排序? STNGS的用戶也總是會看到一致的(提交 - 在內存中的可見性可見)數據?

編輯:對於多個讀者線程和非平凡的設置,這是值得比較簡單的互斥麻煩?

+1

即使不是這樣,這段代碼也完全破壞了。 ('current_settings'可以通過第一行和最後一行之間的其他線程改變。) – ybungalobill 2012-01-09 17:21:14

+0

@DavidSchwartz:考慮char padding [padding_size];在struct的開頭和結尾。另外STNGS可以是指針數組,不會改變,只是指向東西... – NoSenseEtAl 2012-01-09 17:23:23

+0

@NoSenseEtAl這是一個C++的問題或關於某個特定平臺的問題?如果這是一個C++問題,那麼就不能保證填充是你所需要的。如果這是一個特定於平臺的問題,答案將取決於平臺。 (你對'settings'的修改是永遠不會改變的。) – 2012-01-09 17:24:45

回答

0

一般的答案是否定的。如果你很小心,並且只使用具有memory_order參數的函數,並根據你正在做的事情給它們傳遞正確的值,那麼它可能是肯定的。

(和其他人指出,你的代碼有問題。例如,按值返回一個原子<>類型沒有意義對我來說)。

2

給出的定義

int settings[N_STNGS]; 
std::atomic<size_t> current_settings(0); 

和線程1執行:

settings[new_settings] = somevalue; // line A 
current_settings=new_settings;  // line B 

和線程2執行:

int cur_settings = current_settings;  // line X 
int setting_value = settings[cur_settings]; // line Y 

然後是,如果線程2的行X讀取new_settings在B行寫線程1,並且沒有其他修改settings[new_settings](由一些代碼,我們看不到),線程2勢必閱讀somevalue和沒有未定義的行爲發生。這是因爲所有操作都是(默認情況下)memory_order_seq_cst,並且釋放寫入(行B)與獲取讀取(行X)同步。請注意,線程2中需要兩條語句才能獲得索引的原子讀取和值的讀取之間的先後順序關係(取而代之,操作將執行memory_order_consume)。

我肯定會用rw-mutexes來啓動它。

+0

我同意。第X行可以讀取初始值0或B寫入的值之一,在這種情況下,B和X之間存在發生前的關係。A在B之前由程序順序發生,X在Y之前發生。由於發生 - 關係之前的關係是可傳遞的,A發生在Y之前。沒有關係,A和Y中的代碼不是原子的。唯一的擔心是使用循環緩衝區。從理論上講'current_settings'可能包含在X和Y行之間。這將導致A和Y之間的數據競爭。 – 2012-01-10 05:53:13

+0

@BartoszMilewski非常不可能,因爲更新設置每隔幾秒完成一次,所以這將是一些隱藏內存可見性模型(我的意思是這將是最糟糕的高速緩存一致性CPU模型),在這種情況下會出現問題。 – NoSenseEtAl 2012-01-10 08:25:42

+0

可以肯定的是:您是在評論設置*內容*,還是僅僅是圓形陣列設置的索引。 – NoSenseEtAl 2012-01-10 08:34:41