能否请您发表意见?
你将做点什么不同的?
我的意思是,如果我用std::task或std::mutex,std::condition_variable等完成操作,您认为它会更好吗?
我用2个标志来控制线程是一种矫kill过正的做法吗?

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;
}

最佳答案

直言不讳,这在典型的现实硬件上简直令人难以置信。最明显的问题是这样的:

查看increment中的线程。在print运行之前,if将为false,而while将为true。要进行分支预测,将开始坚信if将是false

然后,当print线程将switchFlag设置为false时,由于另一个线程正在等待它,因此您需要increment尽快执行,您将想到可想象的最坏的错误预测分支。

因此,在最关键的一点是尽快执行,这是处理器会给您带来的最糟糕的性能,并用错误的分支炸毁了所有管线。

我强烈敦促您不要尝试从原始操作(例如原子加载和存储)中构成复杂的操作。这样做需要深厚的平台专业知识。对高级操作(如等待)使用高级函数(如互斥锁和条件变量)。

但是,从来没有任何好的方法来实现需要交替执行的两个线程。对于两个线程永远无法同时取得进步的情况,没有充分的理由拥有两个线程。

关于c++ - 以下代码对于多线程增量计数器和打印是否是一个好的解决方案?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60349591/

10-11 22:37
查看更多