拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 多执行绪和指令序列

多执行绪和指令序列

白鹭 - 2022-01-23 2101 0 0

在学习多执行绪编程时,我撰写了以下代码。

#include <thread>
#include <iostream>
#include <cassert>

void check() {
    int a = 0;
    int b = 0;
    {
        std::jthread t2([&](){
            int i = 0;
            while (a >= b) {
                  i;
            }
            std::cout << "failed at iteration " << i << "\n"
                      // I know at this point a and b may have changed
                      << a << " >= " << b << "\n";
            std::exit(0);
        });
        std::jthread t1([&](){
            while (true) {
                  a;
                  b;
            }
        });
    }
}

int main() {
    check();
}

由于 a总是发生在 ba 应该总是大于或等于 b 之前。但实验表明,有时b > a. 为什么?是什么原因造成的?我该如何强制执行?

即使我替换int a = 0;int a = 1000;which 使所有这一切变得更加疯狂。

程序很快退出,因此不会发生 int 溢位。我没有发现可能导致这种情况的汇编中重新排序的说明。

uj5u.com热心网友回复:

因为 a 总是在 ba 之前发生,所以应该总是大于或等于 b

仅在其执行执行绪中并且仅当执行执行绪可以观察到时

C 需要某些显式的“同步”,以便其他执行执行绪可以看到一个执行执行绪所做的更改。

       a;
       b;

仅凭这些陈述句,该执行执行绪实际上无法“区分”是先递增a还是b先递增。因此,C 允许编译器实作它想要的任何优化或代码重新排序步骤,只要它在其执行执行绪中没有可观察到的效果,并且如果实际生成的代码b首先递增,则不会有任何可观察到的效果。这个执行执行绪不可能分辨出差异。

但是,如果有一些中间陈述句“查看”了a,那么这将不再成立,并且编译器将需要a在以某种方式使用它之前实际生成递增的代码

这只是这个执行执行绪,单独存在。即使可以观察到ab此执行执行绪中更改的相对顺序,根据标准,C 编译器也被允许以任何顺序实际递增实际变量,只要还有任何其他调整使此不可观察。但它可以被另一个执行执行绪观察到。为了防止这种情况发生,有必要采取显式同步步骤,使用互斥锁、条件变量和 C 执行执行绪模型的其他部分。

uj5u.com热心网友回复:

在这些不同变量的增量和读取它们之间存在非平凡的竞争条件。如果您想对这些读取和写入进行严格排序,您将不得不使用某种同步机制。std::atomic<> 使它更容易。

试试这个:

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

void check() {
    struct AB { int a = 0; int b=0; };
    std::atomic<AB> ab;
    {
        std::jthread t2([&](){
            int i = 0;
            AB temp;
            while (true) {
                temp = ab;
                if ( temp.a > temp.b ) break;
                  i;
            }
            std::cout << "failed at iteration " << i << "\n"
                      // I know at this point a and b may have changed
                      << temp.a << " >= " << temp.b << "\n";
            std::exit(0);
        });
        std::jthread t1([&](){
            while (true) {
                AB temp = ab;
                temp.a  ;
                temp.b  ;
                ab = temp;
            }
        });
    }
}

int main() {
    check();
}

代码:https : //godbolt.org/z/Kxeb8d8or

结果:

Program returned: 143
Program stderr
Killed - processing time exceeded
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *