std::原子等待操作是如何工作的
How std::atomic wait operation works?
启动C++20时,std::atomic
有wait()
和notify_one()
/notify_all()
操作。但我不知道它们应该如何工作。cppreference说:
执行原子等待操作。表现得好像在重复执行以下步骤:
- 比较此的值表示形式->装载(订单(旧的。
- 如果等于,则阻塞,直到
*this
被notify_one((或notify_all((通知,或者线程被错误地解除阻塞- 否则,返回
这些函数只有在值发生更改时才保证返回,即使底层实现被错误地解锁
我不清楚这两个部分是如何相互关联的。这是否意味着,如果if的值没有更改,那么即使我使用notify_one()
/notify_all()
方法,函数也不会返回?意味着操作在某种程度上等于下面的伪代码?
while (*this == val) {
// block thread
}
是的,正是这样。notify_one/all只是为等待的线程提供了一个检查值是否更改的机会。如果它保持不变,例如,因为不同的线程已将该值设置回其原始值,则该线程将保持阻塞状态。
注意:此代码的有效实现是使用互斥和condition_variables的全局数组。原子变量通过指针通过散列函数映射到这些对象。这就是为什么你会得到虚假的唤醒。一些原子共享相同的条件变量。
类似这样的东西:
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)
{
const std::size_t index = index_for_atomic(ptr);
/*
* normally we don't need to hold the mutex to notify
* but in this case we updated the value without holding
* the lock. Therefore without the mutex there would be
* a race condition in wait() between the while-loop condition
* and the loop body
*/
std::lock_guard<std::mutex> lock(atomic_mutexes[index]);
/*
* needs to notify_all because we could have multiple waiters
* in multiple atomics due to aliasing
*/
atomic_conds[index].notify_all();
}
真正的实现可能会使用操作系统原语,例如Windows上的WaitForAddress或Linux上的futex(至少对于int大小的类型(。
相关文章:
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 当 int 方法工作正常时,void 方法有何不同,或者为什么我不能调用 void 方法?
- sdl软件渲染器不工作,工作在硬件加速的一个