bool compare_exchange_weak (T& expected, T val, ..);
Run Code Online (Sandbox Code Playgroud)
compare_exchange_weak()是C++ 11中提供的比较交换原语之一.它在某种意义上很弱,即使对象的值等于它也会返回false expected.这是由于某些平台上的虚假故障导致一系列指令(而不是x86上的指令)用于实现它.在这样的平台上,上下文切换,由另一个线程重新加载相同的地址(或高速缓存行)等可能使原语失败.这是spurious因为它不是expected操作失败的对象(不等于)的值.相反,这是一种时间问题.
但让我感到困惑的是C++ 11标准(ISO/IEC 14882)中所说的,
29.6.5 ..虚假失败的后果是几乎所有弱比较和交换的使用都将处于循环中.
为什么几乎所有用途都必须处于循环中?这是否意味着我们会因为虚假失败而失败?如果是这样的话,为什么我们compare_exchange_weak()自己打扰使用并编写循环?我们可以使用compare_exchange_strong()我认为应该摆脱我们的虚假失败.有哪些常见用例compare_exchange_weak()?
另一个问题有关.安东尼在他的书"C++ Concurrency In Action"中说,
//Because compare_exchange_weak() can fail spuriously, it must typically
//be used in a loop:
bool expected=false;
extern atomic<bool> b; // set somewhere else
while(!b.compare_exchange_weak(expected,true) && !expected);
//In this case, you keep looping as long as expected is still false,
//indicating that the compare_exchange_weak() …Run Code Online (Sandbox Code Playgroud) 在串行代码中,更新最大值可以简单地通过
template<typename T>
void update_maximum(T& maximum_value, T const& value) noexcept
{
if(value > maximum_value) maximum_value = value;
}
Run Code Online (Sandbox Code Playgroud)
但是,如何对atomic<T>保存最大值的变量执行此操作:
template<typename T>
void update_maximum(std::atomic<T>& maximum_value, T const& value) noexcept
{
// want a lock-free, thread-safe implementation
}
Run Code Online (Sandbox Code Playgroud)
显然,串行版本的代码不起作用,因为另一个线程可能maximum_value在加载和存储之间发生变化.可以使用compare_exchange(比较==而不是>)来实现这个吗?怎么样?
请注意,不允许显式锁定(允许的唯一锁定是执行时可能出现的锁定std::atomic<T>).
在新C++11标准中,许多原子操作在"强/弱"对中定义:
template< class T >
bool atomic_compare_exchange_weak( std::atomic<T>* obj,
T* expected, T desired );
template< class T >
bool atomic_compare_exchange_weak( volatile std::atomic<T>* obj,
T* expected, T desired );
Run Code Online (Sandbox Code Playgroud)
我知道弱者可能会更快,但偶尔会失败,所以需要将它放入while如下的循环中(取自cppreference):
void append(list* s, node* n)
{
node* head;
do {
head = s->head;
n->next = head;
} while(! std::atomic_compare_exchange_weak(s->head, head, n));
}
Run Code Online (Sandbox Code Playgroud)
但
弱行动到底是做什么的?为什么他们有时会失败,为什么他们会更快?(我会喜欢一些核心微处理器架构细节.)
什么时候弱的形式更好,什么时候推荐强者?