代码中经常看见这个关键字Volatile,这个关键字到底是什么意思每次都是似是非懂。在介绍这个关键字之前,先介绍有关线程的几个重要概念。
1、基本概念
首先说一下原子性、可见性、有序性。
1、原子性
原子最先在物理上表示粒子的最小不可分割单元 ,原子性在java内存模型中是指一个操作是不可中断的,最小不可分割单元。即在多个线程一起执行的时候,一个操作一旦开始,就不会被其它线程干扰。
由java内存模型来直接保证的原子性变量操作包括:read、load、assign、use、store和write。可以简单的认为基本数据类型的访问读写是具备原子性的。
在代码层面可以使用synchronied关键字来保证原子性。
2、可见性
当一个线程修改了共享变量的值,其他线程能够立即得知这个修改。
我们知道java里,每个对象有自己独立的内存空间,称为工作内存。这个内存空间和主内存并不是一个东西。一个线程修改了一个共享变量,首先修改的是自己工作内存的值,后同步给主内存。
3、有序性
有序性即程序执行的顺序按照代码的先后顺序执行。
表面上看,代码按照既定顺序执行,何谈有序性。其实不然,在java中,影响代码不按既定顺序执行的原因有“指令重排”以及”工作内存与主内存同步延迟现象“。后一个还好理解,前一个的意思和java内存模型有关。在java代码经过编译器生成字节码的过程中,编译器和处理器对指令进行重排序,即a=a++这种简单的语句是由多条语句组成。编译过后生成的字节码只保证执行结果正确,却不保证中间每条语句的顺序。
2、Volatile关键字
Volatile关键字是java虚拟机提供的最轻量级同步机制。当一个变量被定义为volatile关键字之后,即具备两种特性。第一是保证此变量对所有线程的可见性,意思是当一个线程修改了这个变量的值,新值对于其他线程来说是可以立即得到的;第二是禁止指令重排优化,意思是变量赋值操作顺序与程序中的代码执行顺序一致,而普通变量只能保证执行过程中所有依赖赋值结果的地方都能获取到正确结果。
3、Volatile的使用场景
通常来说,volatile的性能要优于由synchronized关键字或java.util.concurrent这个包里的类。但是由于volatile只提供了轻量级的同步,并不能完全保证同步,所以通常使用在读多写少的场景中。
有关java内存模型及volatile的详细介绍可以参考周志明老师《深入理解java虚拟机》一书的介绍。