volatile关键字

发布时间 2023-09-04 11:56:58作者: 星流残阳

volatile

关键字volatile将变量标记为“存储于主内存中”。
volatile变量的每次读操作都会直接从计算机的主存中读取,而不是从cpu缓存中读取;同样,每次对volatile变量的写操作都会直接写入到主存中,而不仅仅写入到cpu缓存里。

  • 可见性保证
    确保数据变化在线程之间的可见性。
    没有标识volatile的变量,在多线程操作时,每个线程将其拷贝到cpu缓存中进行操作。假如线程1将变量A拷贝到cpu1的缓存中进行修改,而我们不知道什么时候线程1将修改后的变量A重新写入到主内存中,所以无法得知线程2用到变量A时,用的是线程1修改前还是修改后的变量A,即线程间的不可见。而使用volatile进行标识,变量A在修改完后会立即写入到主存中,其他线程调用时也直接在主存中调用,而不是在cpu缓存中。

  • happens-before保证1
    当线程写入volatile变量时,不单单是将这个变量写入主存中。这个线程在写此变量之前改变的所有的变量也将刷新到主存中。当另一个线程读取这个变量时,它也能从主存中读取到随此变量一起被刷入主存的其他所有变量。
    利用此特性,我们只需要将一个或几个变量标识为volatile,就可以在多线程中使用每一个变量,而不是把每个变量都标识为volatile。

  • happens-before保证2
    只要JVM识别出程序的行为在重排序后不会改变,它就会对指令进行重排序以提高性能,而对volatile变量的读取和写入指令不会被JVM重排序。

  • volatile的性能损失
    由于volatile是在主内存中直接进行操作,而不是在cpu缓存中进行,因此性能开销更大。同时,由于volatile阻止了jvm使用优化性能的重排序操作,所以我们只应该在确保多线程中需要变量的可见性时使用volatile关键字。

  • volatile无法满足的情况
    如果线程1和线程2同时对volatile变量A进行修改,线程1将A改为B,线程2将A改为C,那么我们无法得知最终写进主存中的是B还是C。即不满足了变量的原子性,此时需要使用synchronized关键字。