| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> 要是面试官再问我volatile,我就这么答 -> 正文阅读 |
|
[Java知识库]要是面试官再问我volatile,我就这么答 |
回答volatile关键字volatile关键字的三个特性:可见性、禁止指令重排、不保证原子性 1、可见性
①现象:保证了可见性,在进行线程交互中过程中,被该关键字修饰的变量会具有可见性,能够保证变量在线程间的信息是同步的 ②字节码:被该关键字修饰的变量在被编译为字节码的时候,会添加了一个ACC_VOLATILE关键字 ③理论基础:MESI协议,可见性的本质特性是基于计算机的缓存一致性协议。MESI分别对应已修改、独占、共享、无效。之所以该协议能够保证变量在不同线程间具有可见性,就是得益于该协议。 在理解理解MESI协议之前需要了解的一下计算机组成相关的概念:
总结:总线事务总是存在,所以需要总线裁决来决定到底是哪一个进行,常规情况下我们直接使用总线锁定,这样就能够保证数据的安全。但是由于人们希望能够提高处理效率,所以又基于总线窥探机制,提出了一个缓存锁定的理论。将原来的锁定内存块变成了粒度更小的缓存块。 MESI协议(详细版请参考浅谈volatile与计算机缓存一致性协议(MESI)之间的联系): 情景前提为,两个线程共同访问num=1这个变量,MESI协议在这个过程中的体现
总结:简单来说就是,最开始的人拿到了数据就是E,如果第二个人也拿到了数据就变了两个S,如果一个人修改了数据,那么状态就会变成M,然后数据放到主存,与此同时第二个人的就变成I。既然是无效的I,那么第二个人在使用数据的时候就只能自己再去主存中获取,此时获取到的数据,就成个最新的一笔数据。 2、禁止指令重排程序在执行的时候,内部会自动优化掉一些不影响结果的逻辑,这个时候就会涉及代码顺序的调整。那么添加了volatile关键字后,就能够禁止代码结构的优化。编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器进行重排序。编译器选择了比较保守的JMM内存屏障策略,这样就能保证在任何处理器平台上,任何程序中都能够得到正确的volatie内存语义。这个策略分成: LoadStore:在读后面再插入 StoreStore:在写前插入 StoreLoad:在写后插入 LoadLoad:在写读后插入 当然,如果我们只是要解决我们的问题,那么我们添加一个volatile关键字就可以了。如果局部变量也需要使用volatile,那么我们可以手动的添加内存屏障。我们可以使用Java自带的Unsafe工具类,调用对应的方法完成该操作。不过该方法只能通过反射调用。 3、不保证原子性
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 3:01:22- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |