簡體   English   中英

std::atomic 和 std::condition_variable 等待、notify_* 方法之間的區別

[英]Difference between std::atomic and std::condition_variable wait, notify_* methods

我正在查看“原子操作庫”,並遇到了原子“等待”和“通知_ ”方法的新 c++20 功能。 我很好奇 std::condition_variable 的 'wait' 和 'notify_ ' 方法有什么區別

整個使用模式有所不同。

condition_variable變量等待需要互斥鎖。 在通知之前應該使用相同的互斥鎖:

std::mutex mtx;
std::condition_variable cv;

bool condition();
void change_condition();

...

std::unique_lock<std::mutex> lock(mtx);
while (!condition())
{
   cv.wait(lock);
}

...

std::unique_lock<std::mutex> lock(mtx);
change_condition();
lock.unlock();
cv.notify_one();

現在如果你有條件變量的原子,你仍然需要鎖:

std::mutex mtx;
std::condition_variable cv;

std::atomic<bool> condition;

...

std::unique_lock<std::mutex> lock(mtx);
while (!condition.load())
{
   cv.wait(lock);
}

...

std::unique_lock<std::mutex> lock(mtx);
condition.store(true);
lock.unlock();
cv.notify_one();

Atomic 本身不需要帶鎖的保護,因此可以在沒有鎖定的情況下對其進行修改。 但是,仍然需要互斥鎖來與等待同步並避免丟失喚醒。 喚醒線程的替代方法如下:

condition.store(true);
std::unique_lock<std::mutex> lock(mtx);
lock.unlock();
cv.notify_one();

不能省略互斥鎖,即使在通知者端也是如此。

(而且您無法擺脫在lock / unlock中什么都不做的condiion_variable_any和“null mutex”)。


現在,原子等待。 除了在另一個答案中提到的沒有虛假喚醒之外,不需要互斥鎖:


std::atomic<bool> condition;

...

condition.wait(false);

...

condition.store(true);
condition.notify_one();

std:atomic waitnotify_allnotify_one方法類似於條件變量的方法。 它們允許通過使用更高效和輕量級的原子變量來實現以前需要條件變量的邏輯。

wait function 阻塞線程,直到原子 object 的值修改。 它需要一個參數來與原子 object 的值進行比較。 它反復執行:

  • 如果值相等,它會阻塞線程,直到由notify_onenotify_all通知,或者線程被虛假地解除阻塞。
  • 否則,返回。

注意:只有在值發生變化時才保證wait返回,即使底層實現虛假地解除阻塞也是如此。


你可以在這里找到實現: https://github.com/ogiroux/atomic_wait/

策略是這樣選擇的,按平台:

  • Linux:默認為 futex(有表),回退到 futex(無表)-> CVs -> 定時退避 -> 自旋。
  • Mac:默認為 CVs(表格),回退到定時退避 -> 旋轉。
  • Windows:默認為 futex(無表),回退到定時退避 -> 自旋。
  • CUDA:默認為定時退避,回退到自旋。 (此樹中並未全部簽入。)
  • 不明平台:默認為自旋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM