当前位置: 首页 > news >正文

volatile和优化

目录

先看你心里的疑问

编译器的“脑回路”长这样

优化 1:把 stop 读一次,存本地变量

那 volatile 在这里干嘛?

那为什么还说 volatile 不适合多线程同步?

再用一个极简版总结帮你记住


先看你心里的疑问

“我让值是 false,我后面改 true 不行??
什么叫‘这个循环里没人改 stop 啊,那我就当它永远是 false,优化成死循环好了’???”

关键点在于:“我后面改 true”这句话,是在哪儿改的?

  • 如果是同一个线程、同一个函数里改的,编译器当然看得见。

  • 问题是:多线程的时候,常见写法是这样的 👇

// 全局变量
bool stop = false;void worker() {while (!stop) {// 干活}
}int main() {std::thread t(worker);// 过一会儿stop = true;   // 想让 worker 线程停下来t.join();
}
  • worker() 函数里,没有任何代码修改 stop

  • stop = true另一个地方(main 线程)

重点:编译器在编译 worker() 这个函数时,只看它自己的代码。
它不知道“未来会有别的线程来改 stop”。


编译器的“脑回路”长这样

它看到的是这个函数:

void worker() {while (!stop) {// do something}
}

它会想:

“在这个函数里没人改 stop
那么 stop 的值在整个函数执行期间就是不变的。”

于是它“很聪明”地做两件事之一:

优化 1:把 stop 读一次,存本地变量

逻辑相当于:

void worker() {bool tmp = stop;       // 第一次读 stopwhile (!tmp) {         // 后面全用 tmp,不再去内存读 stop// do something}
}

如果刚开始 stop == false,那 tmp == false
那这个循环就变成:

while (true) { ... }   // 永远不会退出

这就是我说的那句人话:

“诶,这个循环里没人改 stop 啊,那我就当它永远是 false,优化成死循环好了”

注意:它不是“真的写成死循环那样的源码”,
效果上等价于死循环——因为它只在一开始读了一次 stop

你在另一个线程里把 stop = true;
worker 线程根本不再去看内存里的新值,它一直用第一次读到的那个 false


那 volatile 在这里干嘛?

如果你写:

volatile bool stop = false;void worker() {while (!stop) {// do something}
}

volatile 对编译器说的是:

“这个变量可能会在你看不见的地方被改,
所以 每次用它的时候都要从内存里重新读一遍
不许:

  • 缓存到寄存器

  • 合并读写

  • 提前读好存起来一直用。”

于是编译器就不敢做“读一次、后面全用本地变量”的优化了,而是类似:

void worker() {while (!stop) {       // 每一圈都去内存读一次 stop// do something}
}

这时候:

  • main 线程把 stop 改成 true

  • worker 每圈都重新读,就有机会看到新值,然后退出循环 ✅

到这一步,你就应该明白这句话了:

volatile = 别优化我对这个变量的访问,每次都老老实实从内存读 / 写。


那为什么还说 volatile 不适合多线程同步?

因为多线程的问题不仅是“看不看到新值”,还有:

  1. 原子性
    比如 x++ 其实是三步:读 → 加一 → 写回。
    两个线程一起 x++,可能互相踩,少加了。

    • volatile int x; x++;
      👉 仍然不是原子操作,还是可能出错。

  2. 操作顺序 & 可见性
    多线程里我们关心:

    • 线程 A 先做了什么

    • 线程 B 什么时候能“保证”看到这些修改
      这需要 happens-before 关系 / 内存序 去保证。
      volatile 完全不管这些,只管“别优化访问”。

std::atomic 就是专门为这些设计的

  • fetch_addstoreload 等操作是原子的

  • 再配合 memory_order(acquire/release/seq_cst)控制线程之间的可见性和顺序。

所以:

  • volatile:只告诉编译器“这变量很特殊,别优化访问”。

  • std::atomic:告诉编译器 + CPU:“这变量要保证多线程下的正确性和同步规则”。


再用一个极简版总结帮你记住

  1. 为什么会有“当它永远是 false,优化成死循环”的效果?

    因为在 worker() 这个函数里,编译器看不到任何修改 stop 的代码,
    所以它以为没谁会改它,就只读一次,后面一直用老值。

  2. volatile 解决的是啥?

    • “这个变量可能会在你看不见的地方被改”

    • 所以你必须每次都从内存读,不能只读一次。

  3. 为什么 volatile 仍然不够?

    • 它不保证 x++ 这种操作是原子的

    • 不保证多线程间的先后顺序 / 可见性

    • 所以只能作为“防优化、硬件寄存器”的工具,
      不是“多线程同步神器”

http://www.dtcms.com/a/618821.html

相关文章:

  • 笔试强训练习-8
  • CodexField Wallet:贯穿创作、资产与智能协作的统一账户层
  • 高并发优惠权益聚合接口的优雅实现(含超时控制 + 来源标识 + Fallback 降级)
  • GrokAI9999 | 支持无敏感AI生图,不限次生成视频
  • 算法题 双指针
  • 问答网站怎么做营销建设单位到江川区住房和城乡建设局网站
  • 大数据实用指南:etl + ambari
  • ONAP网络自动化平台介绍与架构
  • 网站开发确认表购物网站后台模板下载
  • 网站模板安全管理系统外贸网站定做
  • 商务礼品网站模板买卖友情链接
  • 解码线程编程
  • 杰恩设计网站是谁做的百度一下百度一下百度一下
  • 哈希表和冲突处理
  • seo网站建设是什么wordpress首页加广告位
  • 网站开发所需硬件山东建设银行官方网站
  • Adversarial AtA学习(第二十三周周报)
  • 阿里云企业网站备案农村建设自己的网站首页
  • Unity UI框架笔记
  • 15个html5手机网站模板深圳万户网络技术有限公司
  • 网站开发是编程吗网站logoico怎么做
  • 力扣-二叉树的前序遍历
  • 安全联盟可信任网站认证 网站商城系统app开发
  • 做网站的 深圳没有网站做APP
  • 淘宝软件营销网站建设网站建设公司业务培训
  • 【第二十二周】自然语言处理的学习笔记06
  • 重庆ssc做号网站整站外包优化公司
  • Java数据结构-List-栈-队列-二叉树-堆
  • 如何在godaddy空间做手机网站资源wordpress
  • 【科技素养】蓝桥杯STEMA 科技素养组模拟练习试卷 5