c++怎么实现多线程并发_c++ std::thread线程创建与同步【教程】

std::thread仅负责启动线程,安全并发必须配合std::mutex、std::condition_variable或std::atomic;未join/detach会导致析构时terminate;mutex需RAII管理;atomic仅适用于简单原子操作,不能替代mutex保护复合逻辑。

直接说结论:std::thread 本身不提供并发控制,只负责“启动线程”;真正实现安全的多线程并发,必须搭配 std::mutexstd::condition_variablestd::atomic 使用——否则几乎必然出现数据竞争(data race)或未定义行为。

怎么正确创建并管理 std::thread

常见错误是忘记 join()detach(),导致程序在 std::thread 对象析构时调用 std::terminate()

  • std::thread 构造后处于“可连接(joinable)”状态,必须显式调用 join()(等待结束)或 detach()(分离执行)
  • 不要对已 join() 过的线程再次 join(),会抛 std::system_error(错误码为 resource_deadlock_would_occur
  • 避免在线程函数中直接捕获局部变量引用——线程可能比作用域活得久,要用 std::ref() 显式传递引用,或用值捕获([=])、移动捕获([=, arg = std::move(x)]
std::vector threads;
for (int i = 0; i < 4; ++i) {
    threads.emplace_back([i] {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        std::cout << "Thread " << i << " done\n";
    });
}
for (auto& t : threads) t.join(); // 必须等所有线程结束

为什么 std::mutex 不加锁就等于没写

std::mutex 是个“门锁”,但不会自动上锁——你得手动调用 lock() / unlock(),或者更推荐用 std::lock_guard / std::unique_lock RAII 管理。

  • 裸调 mutex.lock() 后忘记 unlock()?一旦异常抛出,锁永远卡住,其他线程死锁
  • std::lock_guard 构造即加锁、析构即释放,最简场景首选;std::unique_lock 支持延迟锁定、条件变量配合、可转移,但稍重
  • 多个互斥量一起锁?用 std::lock(a, b) 配合 std::adopt_lock,避免因加锁顺序不同引发死锁
std::mutex mtx;
int counter = 0;

auto inc = [&]() {
    for (int i = 0; i < 1000; ++i) {
        std::lock_guard lock(mtx); // 自动管理
        ++counter;
    }
};

std::atomic 能替代 mutex 吗

能,但仅限于简单操作:读、写、自增、CAS(compare-and-swap)。它不能保护一段逻辑(比如“先读再判断再写”这种复合操作),也不能保护结构体或对象整体。

  • std::atomic++fetch_add() 是原子的;但 if (a > 5) a = 0; 不是原子的,仍需 mutexcompare_exchange_weak() 手动实现
  • 注意内存序(memory_order):默认 std::memory_order_seq_cst 最安全但略慢;高并发下可降级为 relaxed / acquire / release,但极易出错,不建议新手调
  • 不要对非 POD 类型(如 std::string、自定义类)用 std::atomic——编译失败或行为未定义
std::atomic flag{0};

// 安全:单次原子写
flag.store(1, std::memory_order_relaxed);

// 危险:看似原子,实则不是
if (flag.load() == 1) {
    flag.store(2); // 中间可能被其他线程改写
}

真正难的从来不是“怎么开多个线程”,而是“怎么让它们不踩彼此的脚”。哪怕只共享一个 int,漏掉一个 std::atomic 或少套一层 std::lock_guard,都可能在压测时才暴露问题——而且复现率极低。

相关文章