You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多线程程序是否必须用mutex/conditional_variable?我的解法有漏洞吗?

线程顺序控制解法的可靠性分析

问题背景

给定三个C++函数:

void print1() {
    cout << "one";
    cout.flush();
}
void print2() {
    cout << "two";
    cout.flush();
}
void print3() {
    cout << "three";
    cout.flush();
}

需求是创建三个线程分别执行上述函数,在无法控制CPU调度的前提下,必须保证输出顺序为onetwothree。

通常这类问题会用mutex和condition_variable解决,但有人尝试仅用普通变量实现控制,给出如下解法:

#include <functional>  // function
#include <iostream>
#include <thread>
using namespace std;

class Foo {
    int turn;

public:
    Foo() { turn = 1; }

    void first(function<void()> printFirst) {
        while (turn != 1) {
        }
        printFirst();
        turn = 2;
    }

    void second(function<void()> printSecond) {
        while (turn != 2) {
        }
        printSecond();
        turn = 3;
    }

    void third(function<void()> printThird) {
        while (turn != 3) {
        }
        printThird();
        turn = 1;
    }
};

void print1() {
    cout << "first";
    cout.flush();
}
void print2() {
    cout << "second";
    cout.flush();
}
void print3() {
    cout << "third";
    cout.flush();
}

int main() {
    Foo f;

    thread thread3([&]() { f.third(print3); });
    thread thread2([&]() { f.second(print2); });
    thread thread1([&]() { f.first(print1); });

    thread1.join();
    thread2.join();
    thread3.join();

    return 0;
}

该解法通过Foo类中的turn变量控制线程执行顺序,测试中先启动thread3也能保证输出顺序正确,但疑问在于:这个解法是否存在漏洞?仅考虑到turn的比较与赋值是否为原子操作,但查询得知这些操作是原子的,那该解法是否绝对可靠?

解法的潜在漏洞

这个解法并非绝对可靠,存在两个关键问题:

1. 内存可见性问题

普通的int turn既不是原子类型,也没有任何同步机制(如内存屏障、互斥锁)。虽然单个的读、写操作在多数CPU架构上是原子的,但编译器或CPU可能会对变量进行优化:比如将turn的值缓存到线程的私有寄存器中,导致某个线程修改turn后,其他线程无法及时看到这个更新,会一直卡在while循环中陷入死锁。

这种问题不会在所有测试场景中出现,但在开启编译器优化(如-O2)、或者在弱内存模型的CPU架构(如ARM)上,很容易触发。

2. 忙等的性能浪费

这种while循环的忙等方式会持续占用CPU资源,相比condition_variable的阻塞等待,它不会主动释放CPU,在高负载场景下会显著降低系统整体性能。

修复方案

要让这个解法可靠且高效,有两种常见改进方式:

  • 将turn声明为std::atomic<int>,原子类型会自动保证内存可见性,确保线程间的修改能被及时感知:
    std::atomic<int> turn;
    
  • 改用std::mutex配合std::condition_variable实现阻塞等待,避免忙等的性能消耗,同时保证线程间的同步。

内容的提问来源于stack exchange,提问作者Der Fänger im Roggen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 14:23:09