gez*_*eza 5 c++ multithreading atomic
您能否举一个真实的例子,std::atomic::compare_exchange出于某种原因使用两个memory_order参数版本(因此一个memory_order参数版本不合适)?
在许多情况下,第二个内存排序参数on compare_exchange设置为memory_order_relaxed。在这些情况下,省略它通常没有错,只是效率可能较低。
这是一个简单,无锁的列表/堆栈的示例,该列表/堆栈需要第二个不同的排序参数compare_exchange_weak才能实现无数据争用。
调用push可以并发执行,但是为了避免无锁数据操作的复杂性,我们假设push在执行调用时无法从堆栈中删除节点。即避免悬空的指针。
template<typename T>
class mystack {
struct node {
node *next = nullptr;
T data;
int id;
node(int id) : id{id} { }
};
std::atomic<node *> head{nullptr};
public:
void push(T data, int id);
bool pop(T &data); // not implemented
};
template<typename T>
void mystack<T>::push(T data, int id)
{
node *newnode = new node{id};
newnode->data = std::move(data);
node *current_head = head.load(std::memory_order_relaxed); // A
for (;;)
{
newnode->next = current_head;
if (head.compare_exchange_weak(current_head, newnode,
std::memory_order_release, // B
std::memory_order_acquire)) // C
{
/*
* 'current_head' may not be derefenced here since the initial load (at A)
* does not order memory 'current_head' is pointing at.
*
* a release barrier (at B) is necessary to make 'newnode' available
* to other threads
*/
std::cout << "Insertion successful\n";
break;
} else
{
/*
* 'current_head' is the updated head pointer after 'compare_exchange' failed
* Since it was inserted by another thread (the CAS failed),
* an acquire barrier must be set (at C) in order to be able to access data
* 'current_head' is pointing at.
*/
std::cout << "Insertion failed after head changed to id: " <<
current_head->id << std::endl;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在中push,初始值load(在A处)是放松的操作,这意味着即使head指针是原子加载的,也不能取消引用,因为它所引用的内存在此线程中是无序的。
如果compare_exchange_weak返回成功,newnode则将其插入列表的开头,并通过设置释放屏障(在B处)将其提供给其他线程使用。访问此数据的另一个线程(后来通过pop)需要设置获取屏障。
如果compare_exchange_weak返回失败(错误地忘记),则另一个线程刚刚插入了一个新node实例,并current_head使用的新值进行了更新head。由于current_head现在指向的是在另一个线程中分配和释放的数据,因此如果current_head要取消引用,则需要获取屏障。
这是正确的,因为cout失败消息包括current_head->id。
如果省略最后一个参数,则第一个屏障参数将用于故障load情况,但是由于这是释放屏障,因此有效屏障将衰减到memory_order_relaxed,从而导致数据竞争current_head->id。
| 归档时间: |
|
| 查看次数: |
270 次 |
| 最近记录: |