[英]std::atomic<int> memory_order_relaxed VS volatile sig_atomic_t in a multithreaded program
volatile sig_atomic_t
是否提供任何內存順序保證? 例如,如果我只需要加載/存儲整數,是否可以使用?
例如:
volatile sig_atomic_t x = 0;
...
void f() {
std::thread t([&] {x = 1;});
while(x != 1) {/*waiting...*/}
//done!
}
這是正確的代碼嗎? 有條件可能不起作用嗎?
注意:這是一個過於簡化的示例,即我不想為給定的代碼片段尋找更好的解決方案。 我只是想了解根據C ++標准,在多線程程序中我可以從volatile sig_atomic_t
中得到什么樣的行為。 或者,如果是這種情況,請理解為什么行為未定義。
我在這里發現了以下聲明:
庫類型sig_atomic_t不提供線程間同步或內存排序,僅提供原子性。
如果我在這里將它與這個定義進行比較:
memory_order_relaxed:放松操作:沒有對其他讀取或寫入施加同步或排序約束,只保證此操作的原子性
是不一樣的? 究竟原子性在這里意味着什么? volatile
在這里有用嗎? “不提供同步或內存排序”和“無同步或排序約束”之間有什么區別?
您正在使用sig_atomic_t
類型的對象,該對象由兩個線程訪問(一個修改)。
根據C ++ 11內存模型,這是未定義的行為,簡單的解決方案是使用std::atomic<T>
std::sig_atomic_t
和std::atomic<T>
在不同的聯盟中。在便攜式代碼中,一個不能被另一個替換,反之亦然。
兩者共享的唯一屬性是原子性(不可分割的操作)。 這意味着對這些類型的對象的操作沒有(可觀察的)中間狀態,但就相似性而言。
sig_atomic_t
沒有線程間屬性。 實際上,如果這個類型的對象被多個線程訪問(修改)(如示例代碼中所示),那么它在技術上是未定義的行為(數據競爭); 因此,未定義線程間內存排序屬性。
什么是sig_atomic_t
用於?
這種類型的對象可以在信號處理程序中使用,但前提是它被聲明為volatile
。 原子性和volatile
保證2件事:
例如:
volatile sig_atomic_t quit {0};
void sig_handler(int signo) // called upon arrival of a signal
{
quit = 1; // store value
}
void do_work()
{
while (!quit) // load value
{
...
}
}
雖然這段代碼是單線程的, do_work
可以通過觸發sig_handler
並原子地改變quit
值的信號異步中斷。 如果沒有volatile
,編譯器可能會“ quit
”來自quit
while循環的負載,使do_work
無法觀察到由信號引起的quit
更改。
為什么std::atomic<T>
不能用作std::sig_atomic_t
的替代?
一般來說, std::atomic<T>
模板是一種不同的類型,因為它被設計為由多個線程並發訪問,並提供線程間排序保證。 原子性在CPU級別並不總是可用(特別是對於較大的類型T
),因此實現可能使用內部鎖來模擬原子行為。 std::atomic<T>
是否對特定類型使用鎖定T
可通過成員函數is_lock_free()
或類常量is_always_lock_free
(C ++ 17)獲得。
在信號處理程序中使用此類型的問題是,C ++標准不保證std::atomic<T>
對於任何類型T
都是無鎖的。 只有std::atomic_flag
才有這種保證,但這是一種不同的類型。
想象一下上面的代碼,其中quit
標志是std::atomic<int>
,恰好不是無鎖的。 當do_work()
加載該值時,它有可能在獲取鎖之后但在釋放之前被信號中斷。 該信號觸發sig_handler()
,它現在想通過獲取do_work
已經獲得的同一個鎖來存儲一個值來quit
。 這是未定義的行為,可能導致死鎖。
std::sig_atomic_t
沒有這個問題,因為它沒有使用鎖定。 所需要的只是在CPU級別和許多平台上不可分割的類型,它可以簡單到:
typedef int sig_atomic_t;
底線是,在單線程中使用volatile std::sig_atomic_t
作為信號處理程序,並在多線程環境中使用std::atomic<T>
作為無數據競爭類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.