时间:2021-05-20
前言
笔者去年面试过几家公司,基本上每家公司都会问到volatile,甚至有的公司每轮面试的时候都会问到。面试官这么喜欢问volatile就是因为这个关键字涉及到的知识点较多比如Java内存模型、内存屏障、happen-befor等知识,可以继续挖掘到系统指令、超线程等知识。
Java内存模型(JMM)
volatile是Java虚拟机提供的最轻量的同步机制,但很难被正确的理解与使用,通过学习Java内存模型对volatile专门定义的一些特殊访问规则,或许会对理解volatile有一定帮助。
Java内存模型定义了线程和内存之间关系:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程以读 / 写共享变量的副本。本地内存是 JMM 的一个抽象概念,并不真实存在;它涵盖内存、缓存、寄存器以及其他的硬件和编译器优化。Java的内存模型抽象如下:
volatile的语义
volatile主要提供了两种语义:
1,可见性:
可见性是指一个线程写入的值,其他线程能够立即读取。在由Java内存模型可知道,每个线程都是有本地内存。所以线程A写入在正常情况下,线程B不能立即读取。但是在volatile变量,可以保证线程A不写入本地内存直接写入主内存,线程B直接从主内存中读取,不从本地内存中读取。
2,禁止指令重排序:
重排序是指编译器和处理器为了优化程序性能而对指令进行重排序的一种优化手段。
Java程序的几种重排序
volatile的技术基石--内存屏障
内存屏障是cpu指令,该指令保证特定操作的顺序性和某些内存的可见性。插入一条内存屏障指令之后会告诉编译器和CPU:不管什么指令都不能和这条指令重排序。内存屏障所做的另外一件事情就是强制刷出各种CPU cache,如一个Write-Barrier(写入屏障)将刷出所有在Barrier之前写入cache的数据,因此,任何CPU上的线程都能读取到这些数据的最新版本。
对于Java程序而言,如果把加入volatile关键字的代码和未加入volatile关键字的代码都生成汇编代码,会发现加入volatile关键字的代码会多出一个lock前缀指令。
volatile的典型用例
状态标志,代码示例如下:
线程1执行run()的过程中,可能有另外的线程2调用了shutdown,所以stop变量必须是volatile(利用的volatile的可见性)。
还有一种常见的用法在双重检验的单例实现上,代码如下:
instance = new Singleton()这句,这并非是一个原子操作,事实上在 JVM 中这句话大概做了下面 3 件事情:
如果instance变量没有加volatile,因为指令重排序的存在,就可能导致执行步骤是1-2-3,也可能是1-3-2。一旦是1-3-2,就可能会导致访问未初始化的内存。但是加上volatile关键字之后,一定保证是按照1-2-3步骤执行的(利用的volatile的禁止重排序)。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
前言在Java中,Java中volatile关键字十分重要本文全面&详细解析volatile关键字,希望你们会喜欢目录1.定义Java中的1个关键字/修饰符2.
volatile关键字相信了解Java多线程的读者都很清楚它的作用。volatile关键字用于声明简单类型变量,如int、float、boolean等数据类型。
前言近期看到C++标准中对volatile关键字的定义,发现和java的volatile关键字完全不一样,C++的volatile对并发编程基本没有帮助。网上也
在面试过程中C++的多态实现机制经常会被面试官问道。大家清楚多态到底该如何实现吗?下面小编抽空给大家介绍下多态的实现机制。1.用virtual关键字申明的函数叫
前言在一些开源的框架的源码当中时不时都可以看到volatile这个关键字,最近特意学习一下volatile关键字的使用方法。volatile关键字:当多个线程进