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

Java中持互斥量的共享变量无需volatile,C++中是否同理?

C++中互斥量与共享变量可见性的问题

在Java内存模型(JMM)中,线程A写入字段后解锁互斥量时,该写入操作“先行发生于”解锁操作。这意味着只要两个线程在同一同步块/互斥量下操作共享变量,无需将变量声明为volatile就能保证变更可见性——因为共享互斥量会创建内存屏障。那这个规则在C++中是否同样适用?

参考以下代码:

std::mutex m;
int x = 0;
std::cout << "Starting async:\n";
auto future1 = async(launch::async, 
 [&] {  for (int i = 0; i < 100000; ++i) { m.lock();  ++x; m.unlock(); } });
auto future2 = async(launch::async, 
 [&] {  for (int i = 0; i < 100000; ++i) { m.lock();  ++x; m.unlock(); } });
std::cout << "After calling async. Waiting for result from async:\n";
future1.get(); // wait for thread1
future2.get(); // wait for thread1
std::cout << "x = " << x;

问题答案:不需要将x声明为volatile

C++标准通过互斥量的lock()和unlock()操作定义了明确的**先行发生(happens-before)**关系:

  • 一个线程对某互斥量的unlock()操作,先行发生于后续其他线程对同一互斥量的lock()操作。
  • 线程在获取锁(lock()成功)后执行的所有操作,能够看到之前所有解锁该互斥量的线程对共享变量做出的修改。

在给出的代码中,两个工作线程都通过同一个std::mutex保护对x的修改:每次++x都被包裹在lock()和unlock()之间。线程1的unlock()会先行发生于线程2的lock(),因此线程2能看到线程1对x的最新修改;同理,主线程通过future.get()等待两个线程完成,这一操作也建立了先行发生关系,主线程最后读取x时,能确保看到两个线程的所有修改结果。

另外需要明确:C++中的volatile关键字不提供线程间的同步或可见性保证,它仅用于阻止编译器对变量读写做优化(比如避免将变量缓存到寄存器)。对于已经用互斥量正确保护的共享变量,添加volatile完全多余,甚至可能干扰编译器的正常优化。

内容的提问来源于stack exchange,提问作者Gonen I

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 16:32:25