從 C 20 開始,std::atomic有wait()和notify_one()/notify_all()操作。但我并沒有完全了解它們應該如何作業。cppreference 說:
執行原子等待操作。表現得好像它重復執行以下步驟:
- 比較 this->load(order) 和 old 的值表示。
- 如果它們相等,則阻塞直到
*this由 notify_one() 或 notify_all() 通知,或者執行緒被虛假地解除阻塞。- 否則,回傳。
這些函式保證只有在值發生變化時才回傳,即使底層實作虛假地解除阻塞。
我不完全了解這兩個部分是如何相互關聯的。這是否意味著如果值沒有改變,那么即使我使用notify_one()/notify_all()方法,函式也不會回傳?意味著該操作在某種程度上等于以下偽代碼?
while (*this == val) {
// block thread
}
uj5u.com熱心網友回復:
是的,就是這樣。notify_one/all 只是為等待執行緒提供檢查更改值的機會。如果它保持不變,例如因為不同的執行緒已將該值設定回其原始值,則該執行緒將保持阻塞狀態。
注意:此代碼的有效實作是使用互斥鎖和條件變數的全域陣列。然后原子變數通過它們的指標通過哈希函式映射到這些物件。這就是為什么你會得到虛假的喚醒。一些原子共享相同的條件變數。
像這樣的東西:
std::mutex atomic_mutexes[64];
std::condition_variable atomic_conds[64];
template<class T>
std::size_t index_for_atomic(std::atomic<T>* ptr) noexcept
{ return reinterpret_cast<std::size_t>(ptr) / sizeof(T) % 64; }
void atomic<T>::wait(T value, std::memory_order order)
{
if(this->load(order) != value)
return;
std::size_t index = index_for_atomic(this);
std::unique_lock<std::mutex> lock(atomic_mutexes[index]);
while(this->load(std::memory_order_relaxed) == value)
atomic_conds[index].wait(lock);
}
template<class T>
void std::atomic_notify_one(std::atomic<T>* ptr)
{
/* needs t notify_all because we could have multiple waiters
* in multiple atomics due to aliasing
*/
atomic_conds[index_for_atomic(ptr)].notify_all();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/419342.html
標籤:
下一篇:C 使用cout列印結構
