基本概述
一致性
JVM内存的会分为主内存和线程内存,比如一个对象等数据就会放在主内存的堆里面,堆内存主要是物理内存,如果一个线程需要多次访问主内存中的一个对象,那么就会出现多次物理内存的查找,这样带来的性能损耗会比较大,为了解决这个问题,JVM会把线程使用频繁的对象缓存到线程之中,在缓存中高速访问,那么就会降低损耗。但是在多线程的环境下会出现幻读,或者重复读的问题,为了解决这个问题,Java推出了volatile关键字。
volatile是一个特殊的修饰符,只有成员变量才能使用它。在Java并发程序缺少同步类的情况下,多线程对成员变量的操作对其它线程是透明的。volatile变量可以保证下一个读取操作会在前一个写操作之后发生。线程都会直接从内存中读取该变量并且不缓存它。这就确保了线程读取到的变量是同内存中是一致的。
有序性
JVM在编译字节码的时候,就是把.java文件编译为.class文件的时候,为了将性能优化,有的时候会将指令进行重新排序。这在一些并发场景就会产生一些问题。就比如在双重判断的懒汉单例模式中,对instance判断是否存在那部分代码被两个线程访问,会导致一个线程拿到未完全实例化的一个对象。可以使用volatile来解决这个问题。
用volatile关键字修饰成员变量,可以确保被修饰的成员变量在JVM编译字节码的时候不被重排序。
实现原理
volatile 的底层实现原理是内存屏障,Memory Barrier(Memory Fence)
- 对 volatile 变量的写指令后会加入写屏障
- 对 volatile 变量的读指令前会加入读屏障
如何保证可见性
- 写屏障(sfence)保证在该屏障之前的,对共享变量的改动,都同步到主存当中
- 读屏障(lfence)保证在该屏障之后,对共享变量的读取,加载的是主存中最新数据
如何保证有序性
- 写屏障会确保指令重排序时,不会将写屏障之前的代码排在写屏障之后
- 读

本文介绍了Java中volatile关键字的基本概述、如何保证一致性和有序性。volatile通过内存屏障保证了多线程环境下的可见性和有序性,防止指令重排序。此外,文章还讨论了volatile在解决单例模式的双重检测问题中的作用。
最低0.47元/天 解锁文章
2万+

被折叠的 条评论
为什么被折叠?



