volatile有什么用

1.保证变量对所有线程的可见性

当一个变量被声明为volatile,它会保证对这个变量的写操作立即刷新到主存当中,而对这个变量的读操作会直接从主存中读取,从而确保了多线程环境下对该变量访问的可见性。这意味着一个线程修改了被volatile修饰的变量的值,其他线程能立刻看到这个修改,不会受到各自线程工作内存的影响。

2.禁止指令重排

首先我们先了解一下指令重排,在执行程序时,为了提高性能,处理器和编译器常常会对指令进行重排序,不过指令重排是需要保证在单线程环境下不能改变程序运行的结果以及存在数据依赖关系的不允许重排序。我们熟知的单例模式中的双重检查锁就是为了避免指令重排的问题,在初始化单例对象时,由于编译器或cpu的指令重排,可能会导致另一个线程读取到未初始化完成的对象,这种情况就可以使用volatile关键字来避免。

public class Singleton {
   private static volatile Singleton instance;

   private Singleton() {}

   public static Singleton getInstance() {
       if (instance == null) {
           synchronized (Singleton.class) {
               if (instance == null) {
                   instance = new Singleton();  // 可能会发生指令重排
               }
           }
       }
       return instance;
   }
}

instance = new Singleton()实际上分为三个步骤

1.分配内存空间

2.初始化对象

3.将对象指向内存地址

如果指令重排的话,顺序可能就变为132,接着当正在执行2的时候,另一个线程来读取这个对象,读取到的就是一个未初始化完成的对象

在编程中,`volatile`关键字用于告诉编译器,某个变量的值可能会在程序控制之外发生变化。这种变化可能来源于硬件设备(如寄存器)、多线程环境中的其他线程,或者信号处理程序等。因此,`volatile`关键字的主要作用可以归纳如下: 1. **防止编译器优化**:当一个变量被声明为`volatile`时,编译器将不会对该变量的读写操作进行某些优化,比如将变量缓存到寄存器中或重新排序指令。这确保了每次访问该变量时都会直接从其内存地址读取或写入,而不是使用可能已经缓存的值[^3]。 2. **保证内存可见性**:在多线程环境中,如果一个共享变量被多个线程访问和修改,为了提高性能,每个线程可能会将这个变量缓存到自己的本地缓存中。而`volatile`关键字能够确保一个线程对变量的修改会立即对其他线程可见,从而避免了由于缓存不一致导致的问题[^2]。 3. **维持操作有序性**:虽然`volatile`不能完全禁止处理器级别的指令重排,但它可以在一定程度上通过插入内存屏障来限制特定类型的重排序,以保证跨线程的操作顺序符合预期。例如,在Java中,写入`volatile`变量之前的所有写操作都将在写入该`volatile`变量之后对其他线程可见;同样地,读取`volatile`变量之后的所有读操作都将发生在读取该`volatile`变量之后[^2]。 4. **非原子性保障**:需要注意的是,尽管`volatile`提供了上述特性,但它并不能保证复合操作的原子性。比如对于自增(`++`)这样的操作,即使变量是`volatile`修饰的,也不能保证整个自增过程是原子的。在这种情况下,需要使用额外的同步机制,如互斥锁、原子类(在Java中)或者其他并发工具来保证数据的一致性和完整性[^3]。 综上所述,`volatile`关键字是一个与平台相关的特性,它主要用于那些可能被外部因素改变的变量上,并且在编写底层系统代码、驱动程序以及多线程应用程序时尤为重要。然而,开发者应该清楚地了解它的局限性,特别是在涉及复杂同步需求的情况下。 ```c // 示例:使用 volatile 关键字声明两个整型变量 volatile int var1; volatile int var2; void func() { var1 = 1; // 这个赋值操作将会直接写入内存 var2 = 2; // 同样,这个赋值也会直接写入内存 } ``` 在上面的例子中,`var1`和`var2`都被声明为`volatile`,这意味着它们的值可能会随时被外部因素更改,因此每次访问这些变量时都需要从内存中获取最新的值,而不是依赖于可能已经过期的寄存器副本。此外,这段代码中的赋值操作会被编译器视为必须执行的实际内存写入操作,而不会被优化掉。但是,请注意这里并没有提供任何关于这两个变量之间相对顺序的保证,也就是说,`var1`的更新并不一定先于`var2`对外部观察者可见,除非有进一步的同步机制来强制这种顺序[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值