首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CAS操作中内存屏障的使用

CAS操作中内存屏障的使用
EN

Stack Overflow用户
提问于 2022-11-12 19:29:49
回答 1查看 24关注 0票数 0

在CPP引用的代码片段中,成功和失败分别使用了内存屏障std::memory_order_releasestd::memory_order_relaxed。什么时候可以同时使用std::memory_order_release,或者对两者都使用std::memory_order_relaxed

代码语言:javascript
复制
template<class T>
struct node
{
    T data;
    node* next;
    node(const T& data) : data(data), next(nullptr) {}
};
 
template<class T>
class stack
{
    std::atomic<node<T>*> head;
 public:
    void push(const T& data)
    {
        node<T>* new_node = new node<T>(data);
 
        // put the current value of head into new_node->next
        new_node->next = head.load(std::memory_order_relaxed);
 
        // now make new_node the new head, but if the head
        // is no longer what's stored in new_node->next
        // (some other thread must have inserted a node just now)
        // then put that new head into new_node->next and try again
        while(!std::atomic_compare_exchange_weak_explicit(
                                &head,
                                &new_node->next,
                                new_node,
                                std::memory_order_release,
                                std::memory_order_relaxed))
                ; // the body of the loop is empty
// note: the above loop is not thread-safe in at least
// GCC prior to 4.8.3 (bug 60272), clang prior to 2014-05-05 (bug 18899)
// MSVC prior to 2014-03-17 (bug 819819). See member function version for workaround
    }
};
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-11-12 20:04:25

同时使用relaxed是不安全的。如果compare_exchange成功,则head将被更新为new_node值,其他读取head的线程将得到该指针。但是,如果没有发布顺序,写入new_node->next (现在的head->next)的值可能还不能全局可见,因此如果其他线程试图读取head->next,它可能会看到垃圾,或者以其他方式出现错误行为。

形式上,对new_node->next的写入需要在任何其他线程尝试读取它之前进行,这只能通过在存储区上进行发布命令来确保,该存储指示其他线程该值已就绪。(同样,读取head的线程需要使用获取排序。)通过对成功存储进行轻松的排序,在关系不存在之前就发生了,因此代码有一个数据竞争,其行为是未定义的。

对这两种情况都使用release是没有意义的,因为发布命令只对存储有意义,而在失败的情况下,不执行存储。事实上,由于这个原因,为故障排序传递std::memory_order_release实际上是非法的;这是在获取示例代码的页面上说明的。使用acquireseq_cst是安全的(更强的排序总是安全的),但是没有必要,可能会造成不必要的性能损失。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74415931

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档