以下代码是多线程增量计数器和打印的好解决方案吗?

anc*_*anc 1 c++ multithreading c++11 stdatomic

请你给点意见好吗?你将做点什么不同的?我的意思是,你认为如果我用 std::task 或 std::mutex、std::condition_variable 等来做会更好吗?我用 2 个标志来控制线程是一种矫枉过正吗?

std::atomic<int> counter = { 0 };
std::atomic<bool> switchFlag = { false };
std::atomic<bool> finished = { false };
constexpr int MAX_NUM = 10;

void increment(){
    while (!finished.load()){
        if (!switchFlag.load()){
            std::cout << "incremented to =" << ++counter << '\n';
            switchFlag.store(true);
        }
    }
}

void print(){
    while (!finished.load()) {
        if (switchFlag.load()){
            std::cout << "counter=" << counter.load() << '\n';
            if (counter.load() >= MAX_NUM)
                finished.store(true);

            switchFlag.store(false);
        }
    }
}

int main() {
    auto t1 = std::thread(increment);
    auto t2 = std::thread(print);
    t1.join();
    t2.join();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*rtz 5

坦率地说,这在典型的现实硬件上是令人难以置信的糟糕。最明显的问题是:

看看里面的线程increment。直到print运行,if意志false和while意志是真实的。对分支预测将开始变得坚信if将是false。

然后,当print线程设置switchFlag为false并且您需要increment尽快执行时,因为另一个线程将等待它,您将采用可以想象的最糟糕的错误预测分支。

因此,在您尽快执行最关键的时刻,您会遇到处理器可以提供给您的最差性能,用错误预测的分支炸毁所有管道。

我强烈建议您不要尝试用原子加载和存储等原始操作组合复杂的操作。这样做需要深厚的平台专业知识。将高级函数(如互斥体和条件变量)用于高级操作(如等待)。

但是从来没有任何好的方法来实现两个需要交替执行的线程。对于两个线程不能同时向前推进的任何情况,没有充分的理由拥有两个线程。