volatile是一个被遗忘的关键字,在开发串行程序当中不会使用,而并行程序当中也不能代替锁(synchronized)(大多数情况下).但开发当中若然巧妙使用volatile,将避免不必要的加锁操作.
在并行程序开发当中操作变量需要注意两个问题.一个是安全性(正确性),另一个是内存可见性.当多个线程同时操作一个变量时,可以使用锁来保证操作变量的安全性和内存可见性,但若然当操作结果不需要依赖上一个结果,而仅仅只作为一个标识,则可以使用volatile来代替加锁.
以下代码不需要线程安全性,仅仅将变量作为退出线程的标识.但遗憾的是该程序有可能永远无法退出.
Java代码
- public class Application {
- private static boolean flag = false;
- private static int number;
- public static void main(String[] args) throws InterruptedException {
- new Test().start();
- Thread.sleep(1000);
- number = 50;
- flag = true;
- }
- private static class Test extends Thread {
- @Override
- public void run() {
- while (!flag) {
- System.out.println(number);
- }
- }
- }
- }
volatile是Java提供的一种稍弱的同步机制,用来增大被修饰变量的内存可见性,从而达到将变量的更新操作通知到其他线程.若然访问volatile修饰的变量将会到主存(堆)当中获取.而不会读取线程的变量副本,被修饰的变量亦不会被缓存到寄存器或者对其他处理器不可见的地方.volatile只承诺被修饰变量的内存可见性,而不保证变量是否被正确的操作,因此volatile从语义或使用上都不能替代锁.因此当遇到以下场景时,可考虑使用volatile.
1.对变量的操作不依赖变量的当前值.
2.能确保只有一个线程对其进行修改.
3.修改变量不影响程序正确性.
总结:
在某些情况下使用volatile能避免不必要的加锁操作,尽管有更多或更好的方案代替volatile,但亦可以了解这个关键字的使用方法,必要时多一套解决方案.而在性能方面对比加锁的线程挂起/恢复开销,每次访问变量都需要去主存获取的volatile可以说是忽略不计.
时间: 2024-10-11 07:23:34