Java 关键字 volatile 修饰变量
并发程序正确地执行,必须要保证原子性、可见性以及有序性。只要有一个没有被保证,就有可能会导致程序运行不正确。
原子性:一个操作或多个操作要么全部执行完成且执行过程不被中断,要么就不执行。
即操作不可再分(在汇编层面看为一条机器指令),比如a = 1, 和 return a 分别具有原子性, 但 “a += b”可能需要经过三个步骤:mov eax,dword ptr [a]add eax,dword ptr [b]mov dword ptr [a],eax
可见性:当多个线程同时访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
Volatile实现内存可见性是通过store和load指令完成的;也就是对volatile变量执行写操作时,会在写操作后加入一条store指令,即强迫线程/进程将最新的值刷新到主内存中;而在读操作时,会加入一条load指令,即强迫从主内存中读入变量的值。
有序性:程序执行的顺序按照代码的先后顺序执行。
volatile 关键字的作用就是告诉编译器,凡是被该关键字声明的变量都是易变的,不稳定的。
所有不要试图对该变量使用缓存等优化机制,而应当每次都从它的内存地址中去读值。
使用volatile标记的变量在读取或写入时,不需要使用锁,这将减少产生死锁的概率,使代码保持整洁。
注:每次读取volatile的变量时,都要从它的内存地址中读取,并没有说每次修改完volatile的变量后,都要立刻将它的值写回内存。
volatile只提供了内存可见性,而没有提供原子性。
所以说用这个关键字做高并发的安全机制的话是不可靠的。
用法:
1 public volatile static int count = 0;
最好是那种只有一个线程修改变量,多个线程读取该变量的地方。也就是对内存可见性要求高的,而对原子性要求低的地方。
volatile 与加锁机制的主要区别是:加锁机制既可以确保可见性,又可以确保原子性,而volatile变量只有确保可见性。
加锁机制,比如Synchronized:保证可见性和原子性
Synchronized能够实现原子性和可见性;在Java内存模型中,synchronized规定,线程在加锁时,先清空工作内存→在主内存中拷贝最新变量的副本到工作内存→执行完代码→将更改后的共享变量的值刷新到主内存中→释放互斥锁。
更多线程安全链接: