代码之家  ›  专栏  ›  技术社区  ›  getsoubl

C++11内存订购获取发布问题

  •  1
  • getsoubl  · 技术社区  · 2 年前

    基于标准,有以下示例

    #include <atomic>
    #include <cassert>
    #include <thread>
     
    std::atomic<bool> x = {false};
    std::atomic<bool> y = {false};
    std::atomic<int> z = {0};
     
    
        void write_x()
        {
            x.store(true, std::memory_order_seq_cst);
        }
         
        void write_y()
        {
            y.store(true, std::memory_order_seq_cst);
        }
         
        void read_x_then_y()
        {
            while (!x.load(std::memory_order_seq_cst))
                ;
            if (y.load(std::memory_order_seq_cst))
                ++z;
        }
         
        void read_y_then_x()
        {
            while (!y.load(std::memory_order_seq_cst))
                ;
            if (x.load(std::memory_order_seq_cst))
                ++z;
        }
         
        int main()
        {
            std::thread a(write_x);
            std::thread b(write_y);
            std::thread c(read_x_then_y);
            std::thread d(read_y_then_x);
            a.join(); b.join(); c.join(); d.join();
            assert(z.load() != 0); // will never happen
        }
    

    基于x/y的标准负载,在存储x/y之后发生。因此,不会激发断言 如果以上代码更改如下

    #include <atomic>
    #include <cassert>
    #include <thread>
     
    std::atomic<bool> x = {false};
    std::atomic<bool> y = {false};
    std::atomic<int> z = {0};
     
    void write_x()
    {
        x.store(true, std::memory_order_release);
    }
     
    void write_y()
    {
        y.store(true, std::memory_order_release);
    }
     
    void read_x_then_y()
    {
        while (!x.load(std::memory_order_acquire))
            ;
        if (y.load(std::memory_order_acquire))
            ++z;
    }
     
    void read_y_then_x()
    {
        while (!y.load(std::memory_order_acquire))
            ;
        if (x.load(std::memory_order_acquire))
            ++z;
    }
     
    int main()
    {
        std::thread a(write_x);
        std::thread b(write_y);
        std::thread c(read_x_then_y);
        std::thread d(read_y_then_x);
        a.join(); b.join(); c.join(); d.join();
        assert(z.load() != 0); // will never happen
    }
    

    然后断言被激发。 但我的问题是,其他线程何时知道存储值x/y? 基于该标准,有以下声明

    从线程A的角度来看,在原子存储之前发生的所有内存写入(包括非原子和松弛原子)都会在线程B中产生可见的副作用。也就是说,一旦原子加载完成,线程B就可以保证看到线程A写入内存的所有内容。只有当B实际返回A存储的值,或者在发布序列的后面返回的值时,这个承诺才有效。

    线程写入值x。当线程c或d加载变量x时,线程B是否知道新的值x? 引发断言的种族条件究竟是什么?

    1 回复  |  直到 2 年前
        1
  •  2
  •   Jeff Garrett    2 年前

    基于x/y的标准负载,在存储x/y之后发生。因此,不会激发断言

    更准确地说,顺序一致操作的单个总修改顺序意味着存储x、存储y和负载的操作发生在 一些 顺序

    特别地,在这个修改顺序中,x的存储或y的存储首先发生。假设它是x。然后,在等待y为true的线程中,它必须为x加载true。

    引发断言的种族条件究竟是什么?

    没有排序。read_x_then_y可以加载x true然后加载y false,read_y_then_x可以加载y true然后加载x false。