Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何制作轻型负载存储屏障_C++_Multithreading_Concurrency_Memory Barriers - Fatal编程技术网

C++ 如何制作轻型负载存储屏障

C++ 如何制作轻型负载存储屏障,c++,multithreading,concurrency,memory-barriers,C++,Multithreading,Concurrency,Memory Barriers,例如,如果我们有两个std::atomics,并且希望从第一个读取值,然后将第二个标记为我们不再需要第一个的值。我们不希望这些操作被重新排序(否则第一个值可以在我们读取它之前被重写),但是操作之间没有数据依赖性,所以我们确实需要一个屏障来防止重新排序(而且内存顺序\u消耗不适合) 这里的篱笆太满了。此外,我们既不需要释放也不需要获取语义(即使它们提供了这样的障碍)。我们所需要的只是保持读写操作的顺序 有没有便宜的篱笆可以满足我们的需要 编辑:我需要的例子 std::atomic<X>

例如,如果我们有两个
std::atomic
s,并且希望从第一个读取值,然后将第二个标记为我们不再需要第一个的值。我们不希望这些操作被重新排序(否则第一个值可以在我们读取它之前被重写),但是操作之间没有数据依赖性,所以我们确实需要一个屏障来防止重新排序(而且
内存顺序\u消耗
不适合)

这里的篱笆太满了。此外,我们既不需要释放也不需要获取语义(即使它们提供了这样的障碍)。我们所需要的只是保持读写操作的顺序

有没有便宜的篱笆可以满足我们的需要

编辑:我需要的例子

std::atomic<X> atomicVal;
std::atomic<bool> atomicFlag = false;
...

auto value = atomicVal.load(std::memory_order_relaxed);
some_appropriative_fence();
atomicFlag.store(true, std::memory_order_relaxed);
但这对我们需要的手术来说太贵了

我很感兴趣的是,最小的围栏足以保证操作顺序。

更新后:

您希望原子标志和变量使用以下内容写入(存储):

您希望通过以下方式读取标志和值:

p2 = ptr.load(std::memory_order_acquire)
这似乎就是它们存在的确切原因

编辑2:事实上,释放消耗可能更好。但我从来没见过它被使用过。上面的链接还指出:

 Note that currently (2/2015) no known production compilers track dependency chains: consume operations are lifted to acquire operations.
编辑3:示例代码执行类似于我理解的您想要的操作

#include <thread>
#include <iostream>
#include <atomic>

std::atomic<int> x;
std::atomic<int> y;

auto write_op = std::memory_order_release;
auto read_op = std::memory_order_acquire;

// auto write_op = std::memory_order_seq_cst;
// auto read_op = std::memory_order_seq_cst;

void consumer()
{
    while(true)
    {
        int rx,ry;
        do
        {
            ry = y.load(read_op); // flag read first to guarantee x validity
            rx = x.load(read_op);
        }
        while(ry == 0); // wait for y. y acts as the flag, here

        if (ry == -1)
        {
            break;
        }

        if (rx != ry) // check consistency
        {
            std::cout << "Boo " << rx << " " << ry << std::endl;
        }

        x.store(0, write_op);
        y.store(0, write_op);
    }
}

void producer()
{
    int count = 0;
    int steps = 0;
    while(steps < 50)
    {
        while(y.load(read_op) != 0) {} // wait for y to have been consumed

        int value = std::rand() % 10 + 1;

        x.store(value, write_op); // stores values
        y.store(value, write_op); // indicates readiness to other thread

        count++;
        if (count == 1000000)
        {
            std::cout << '.' << std::endl;
            count = 0;
            steps++;
        }
    }
    y.store(-1);
}

int main()
{
    x = 0;
    y = 0;

    std::thread thread1(producer);
    std::thread thread2(consumer);

    thread1.join();
    thread2.join();
}
#包括
#包括
#包括
std::原子x;
std::原子y;
自动写入\u op=std::内存\u顺序\u释放;
自动读取\u op=std::内存\u顺序\u获取;
//自动写入\u op=std::内存顺序\u顺序\u cst;
//自动读取=标准::内存顺序顺序cst;
无效消费者()
{
while(true)
{
int rx,ry;
做
{
ry=y.load(read_op);//首先读取标志以保证x的有效性
rx=x.负载(读取操作);
}
while(ry==0);//等待y。y作为标志,在这里
如果(ry==-1)
{
打破
}
if(rx!=ry)//检查一致性
{

std::cout为了确保您得到最佳答案,您能否发布一个代码段,其中两个变量是读/写的,预期输出和示例输出都是不受欢迎的?如果您的代码将在x86上执行,则Intel体系结构保证了这一点:“写入不会用旧的读取重新排序。”是的,但我的目标是弱内存模型,其中任何操作都可以重新排序。是的,代码> SEQJCST 当然适合,但我认为它是多余的,并且对最便宜的可能的栅栏感兴趣。那么,我怀疑你可以安全地捕获/释放。然后,当我们读一读然后写一篇文章时,我们可以考虑单释放或获取屏障,这对这两个O来说足够了。不相互重新排序的操作?如果原子标记存储在线程A中的order_release中,当线程B将order_acquire加载它时,它将保证看到原子值写入(以前已完成)。但是,要使其起作用,您必须保证在写入atomic_标志后不会发生其他atomic_val写入。通常,在读取后执行相反的过程,将标志存储回false。
 Note that currently (2/2015) no known production compilers track dependency chains: consume operations are lifted to acquire operations.
#include <thread>
#include <iostream>
#include <atomic>

std::atomic<int> x;
std::atomic<int> y;

auto write_op = std::memory_order_release;
auto read_op = std::memory_order_acquire;

// auto write_op = std::memory_order_seq_cst;
// auto read_op = std::memory_order_seq_cst;

void consumer()
{
    while(true)
    {
        int rx,ry;
        do
        {
            ry = y.load(read_op); // flag read first to guarantee x validity
            rx = x.load(read_op);
        }
        while(ry == 0); // wait for y. y acts as the flag, here

        if (ry == -1)
        {
            break;
        }

        if (rx != ry) // check consistency
        {
            std::cout << "Boo " << rx << " " << ry << std::endl;
        }

        x.store(0, write_op);
        y.store(0, write_op);
    }
}

void producer()
{
    int count = 0;
    int steps = 0;
    while(steps < 50)
    {
        while(y.load(read_op) != 0) {} // wait for y to have been consumed

        int value = std::rand() % 10 + 1;

        x.store(value, write_op); // stores values
        y.store(value, write_op); // indicates readiness to other thread

        count++;
        if (count == 1000000)
        {
            std::cout << '.' << std::endl;
            count = 0;
            steps++;
        }
    }
    y.store(-1);
}

int main()
{
    x = 0;
    y = 0;

    std::thread thread1(producer);
    std::thread thread2(consumer);

    thread1.join();
    thread2.join();
}