volatile关键字的作用

volatile关键字的作用

首先需要介绍一下并发的三个属性。

原子性

  • 为什么叫原子性呢,因为原子就是不可拆分的了。所以原子性指的就是,一个操作或者多个操作不会被别的因素打断,要不就一起执行,要不就一起都不执行。
  • 比如在mysql中事务的操作也具有原子性。
  • 常见的原子性操作有
    • 直接对变量进行赋值
    • 所有引用reference的赋值操作
    • java.concurrent.Atomic包里面的操作

可见性

  • 可见性指的是在多线程的情况下,如果有一个线程进行了变量的修改,那其他的线程都能看到。
  • java中一般用volatile关键字来保证可见性
  • 其原理是当一个变量被volatile关键字修饰了以后,线程本地的内存就无效了,会被存放到主内存中。

有序性

  • 有序性指的是java的程序运行是不是按照代码的顺序来运行的。
  • 在单线程的时候,一定是有序的。(线程内表现为串行语义)
  • 但如果是多线程的情况下,不一定会有序。(重排序)
  • volatile可以保证一定的有序性(比如单例模式中的dcl双重检查锁)
  • synchronized和lock也可以保证,因为同一时间只有一个线程在工作

锁具有可见性和互斥性

  • 互斥性指的是一次只允许一个线程持有某个特定的锁,一次就只有一个线程能够使用该共享数据
  • 可见性就是上面描述的

volatile的特性

  • 写一个volatile变量的时候,JMM会强制把这个值从线程本地内存写到主内存中(保证可见性)
  • 禁止指令重排序
    • 因为jvm内部如果一条程序的先后顺序不影响其逻辑,那么有可能会进行指令重排序
    • 比如a = 2; b =3 ; c= a+b;我们写上去的是这样的,但是在虚拟机内部可能会进行重排序 比如先给b赋值3再给a赋值2,但是a+b一定是最好处理的,因为要保证最后输出的结果是c=a+b=5;
    • 再举一个代码的例子(伪)
memory = allocate(); //1.分配对象内存空间
instance(memory);    //2.初始化对象
instance = memory;   //3.设置instance指向刚分配的内存地址,此时instance!=null

memory = allocate(); //1.分配对象内存空间
instance = memory;   //3.设置instance指向刚分配的内存地址,此时instance!=null
instance(memory);    //2.初始化对象
    • 上面的就是相当于new一个新对象的时候内存的变动,在单线程的时候这样变动是无所谓的,但是如果是多线程的话,可能会导致instance指向一个已经被分配的内存地址。

应用volatile特性写的一个DCL(双重检查锁)单例模式

public class DCL {
	private volatile static DCL dcl;

	private DCL(){}

	public static DCL getInstance() {
		if(dcl == null){ //此处是第一次检查
			Syncronized(DCL.class){
				if(dcl == null) {//此处是第二次检查
					dcl = new DCL;
				}
			}
		}
		return dcl;
	}
}

为什么要这么写 就是因为上面伪代码中,初始化对象和为新对象分配内存地址的时候发生了重排序,位置变动了,就导致第二个线程认为dcl已经不是空了(因为他已经有了指向的内存地址,尽管还没有被初始化),从而直接return了一个空的没有被初始化的dcl实例对象。

volatile的原理

  • 通过内存屏障来实现的,如果反编译class文件你会发现,会多一行lock指令,这就是内存屏障
  • 内存屏障提供的功能
    • 内存屏障前后的东西不会因为指令重排序而导致位置互换。也就是所谓的当cpu执行到内存屏障的内容时,前面的一定全部完成。
    • 强制将对缓存的修改(本地内存)写入到主内存中。
    • 如果是写操作,会强制其他的cpu核心中的缓存行无效。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值