栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

synchronized和volatile

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

synchronized和volatile

前言:在早期,多核CPU使用锁总线的方式解决缓存同步问题,即一旦遇到lock指令便由仲裁器选择一个内核独占总线(cas做了锁了总线或缓存行还是volatile做了锁总线或缓存行? - 知乎),其他内核相当于被阻塞搁置,总线连接各缓存、内存等硬件故锁总线效率很低,后来改用锁缓存(行)。

自从多核CPU出现后用MESI可严格保证缓存一致性,即CPU1中对共享变量修改后CPU2能立刻感知到,即可见性。但CPU受限于(需要等待)信号在核间的来回传输,因而出现了store buffer和invalid queue,但会导致重排序,即CPU1中两指令的顺序在CPU2的感知中是相反的,即有序性。用synchronized可同时保证原子性、可见性和有序性,其中原子性通过lock/unlock原子操作实现,后两者通过内存屏障实现(汇编代码中lock#指令与内存屏障的关系,volatile的底层是lock#指令还是内存屏障? - 知乎),volatile没用锁故只可保证后两者,只能在一定程度上保证线程间的同步,反例如两线程对贡献变量做i++仍会出错(https://www.jb51.net/article/41185.htm)。

另外,用store buffer后能体现volatile变量和普通变量的区别的例子如状态标记量和单例模式double check(java volatile关键字解惑 - 简书),根本原因是线程1修改共享变量后会先invalidate其他CPU缓存再触发内存屏障保证store buffer尽快生效故线程2再读时会重新从内存/其他CPU缓存(二者是一回事,详见实战指南)中读到最新值。

综上,我认为MESI、volatile和synchronized三者之间是功能逐层递进/逐步增强/逐步完善的关系。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/297872.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号