volatile关键字只能修饰变量,不能修饰类,也不能修饰方法。
想要把某个变量共享,该变量的读写操作必须是原子性的,并用volatile关键字修饰。
volatile修饰的long和double类型的变量读写操作是原子性的。long和double都是64位的,给long和double类型的变量赋值跟平台相关,在有些平台上不是原子操作。很多平台给long和double变量赋值需要2步操作,每一步只写32位,在这2个步骤之间,其他线程获取的long或double类型的变量的值的状态是不正确的。
volatile变量有类似synchronized同步代码的可见性,即每个线程读取到的都是最新更新的值。volatile的局限性很大,你只能获取volatile变量的值,直接设置volatile变量的值,不能比较之后再设置volatile的值,因为在你做比较操作的区间很有可能有其他线程修改了该volatile变量的值。
被volatile关键字修饰,表明该变量是要被多个线程访问的,编译器不会对与volatile变量相关的代码做重排或其他多线程下不允许的优化。没有被volatile关键字修饰,编译器会重排代码,缓存变量的值,减少从主存中直接获取变量的值。
用例子来详细彻底说明Java的volatile关键字工作原理
不用volatile关键字修饰,有可能某个线程可以获取到另一个线程设置的isActive的值,编译器有可能缓存了isActive的值等等,使用volatile关键字可以避免这些情况。
双重检查单例模式在JDK4是有问题的,volatile可以修复这个问题。本文的《第一个例子说明volatile变量的含义》中举的例子就是说这个问题。
volatile关键字的总结
-
volatile关键字只用修饰变量,不能修饰方法和类。
-
volatile变量的值都是从主存中获取的,而不是从线程的本地内存。
3.long和double变量被volatile关键字修饰之后,读写(赋值操作,读取操作)都是原子操作.
-
使用volatile关键字可以避免内存不一致的错误;写入volatile变量一定会比接下来的读操作先发生。5. 从jdk5开始对volatile变量的修改对其他的线程都是可见的;当线程读取volatile变量的时候,会先把其他线程中缓存着的volatile变量(如果还没有更新到主存中的时候)强制写入到主存。
-
除了long和double其他的基本类型读写操作都是原子性的;引用类型的读写操作也是原子性的。
-
volatile变量只能做简单的读写,没有锁,没有阻塞。
8.volatile变量可以是空的.
-
volatile不能保证原子性,比如volatile修饰的int变量++操作还是非原子的。
-
变量没有在多个线程之间共享,没有必要做任何同步的操作,比如使用volatile关键字修饰。