6月1日 09:46

C++ 多线程怎么写?mutex/条件变量/atomic/future 详解

C++11 起 <condition_variable> 是并发编程的核心。std::thread 创建线程,必须 join() 或 detach(),否则析构时 terminate。共享数据用 std::mutex 保护,lock_guard 在作用域自动加解锁,unique_lock 支持手动加解锁和配合条件变量。condition_variable 解决生产者-消费者问题:wait 释放锁并阻塞,notify_one/all 唤醒等待线程,注意用谓词版本 wait(lock, pred) 防虚假唤醒。std::atomic 无锁原子操作,支持 fetch_add、compare_exchange_weak(CAS),可选内存顺序。std::async 启动异步任务返回 future,get() 阻塞等结果。死锁避免:固定加锁顺序或用 std::lock 同时加多个锁。

追问

lock_guard 和 unique_lock 有什么区别?

lock_guard 构造加锁析构解锁,不可手动控制,轻量。unique_lock 同样 RAII 但支持手动 lock/unlock、defer_lock 延迟加锁、配合 condition_variable 的 wait。只用简单的临界区保护用 lock_guard,需要条件变量或灵活控制用 unique_lock。

条件变量为什么会有虚假唤醒?

POSIX 标准允许条件变量在没有 notify 的情况下唤醒,这是实现上的妥协。所以必须用 while 循环或谓词版本 wait(lock, pred) 检查条件,不能假设被唤醒就代表条件成立。

memory_order_relaxed 和 memory_order_seq_cst 有什么区别?

relaxed 只保证原子操作本身的原子性,不保证操作间的顺序可见性,性能最好但容易出 bug。seq_cst 是默认顺序,全局顺序一致,所有线程看到相同的操作顺序。绝大多数情况用默认 seq_cst,只有确认安全的性能热点才降级到 acquire/release 或 relaxed。

std::async 和直接创建 thread 有什么区别?

async 返回 future,能拿到返回值和异常;thread 拿不到返回值,异常会导致 terminate。async 的 launch::policy:async 强制新线程,deferred 延迟到 get() 时在当前线程执行。默认策略由实现决定,要保证异步就传 launch::async。

标签:C++