C++11内存排序获取释放问题

问题描述 投票:0回答:1

根据标准有以下示例

#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? 触发断言的竞争条件到底是什么?

c++ c++11 memory-model
1个回答
0
投票

基于 x/y 的标准加载发生在 x/y 存储之后。因此,没有断言被触发

更准确地说,顺序一致操作的单一总修改顺序意味着存储 x、存储 y 和加载的操作按some 顺序发生。

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

触发断言的竞争条件到底是什么?

没有订单。 read_x_then_y 可能加载 x true,然后 y false,read_y_then_x 可能加载 y true,然后 x false。

© www.soinside.com 2019 - 2024. All rights reserved.