Volatile实现原理以及应用附加相关面试题

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

基本概述

一致性

JVM内存的会分为主内存和线程内存,比如一个对象等数据就会放在主内存的堆里面,堆内存主要是物理内存,如果一个线程需要多次访问主内存中的一个对象,那么就会出现多次物理内存的查找,这样带来的性能损耗会比较大,为了解决这个问题,JVM会把线程使用频繁的对象缓存到线程之中,在缓存中高速访问,那么就会降低损耗。但是在多线程的环境下会出现幻读,或者重复读的问题,为了解决这个问题,Java推出了volatile关键字。

volatile是一个特殊的修饰符,只有成员变量才能使用它。在Java并发程序缺少同步类的情况下,多线程对成员变量的操作对其它线程是透明的。volatile变量可以保证下一个读取操作会在前一个写操作之后发生。线程都会直接从内存中读取该变量并且不缓存它。这就确保了线程读取到的变量是同内存中是一致的。

有序性

JVM在编译字节码的时候,就是把.java文件编译为.class文件的时候,为了将性能优化,有的时候会将指令进行重新排序。这在一些并发场景就会产生一些问题。就比如在双重判断的懒汉单例模式中,对instance判断是否存在那部分代码被两个线程访问,会导致一个线程拿到未完全实例化的一个对象。可以使用volatile来解决这个问题。

用volatile关键字修饰成员变量,可以确保被修饰的成员变量在JVM编译字节码的时候不被重排序。

实现原理

volatile 的底层实现原理是内存屏障,Memory Barrier(Memory Fence)

  • 对 volatile 变量的写指令后会加入写屏障
  • 对 volatile 变量的读指令前会加入读屏障

如何保证可见性

  • 写屏障(sfence)保证在该屏障之前的,对共享变量的改动,都同步到主存当中
  • 读屏障(lfence)保证在该屏障之后,对共享变量的读取,加载的是主存中最新数据

如何保证有序性

  • 写屏障会确保指令重排序时,不会将写屏障之前的代码排在写屏障之后
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值