java的volatile理解

https://blog.csdn.net/OOC_ZC/article/details/78477565 案例
https://blog.csdn.net/OOC_ZC/article/details/85053048 解释
https://blog.csdn.net/swadian2008/article/details/99696399

首先解释一下,什么叫指令排序:
案例一:

重排序是这样的概念,
比如 

int i=1;
boolean flag=true;
i=2;
flag=false;

你代码是这么写的,但是真正在运行的时候,jvm可能先执行flag=false,然后执行i=2.
这就是指令重排序,但是他会保证你这段代码执行完确保你i=2,flag=false,只不过中间过程,
他可能会先给flag赋值为false,然后再给i赋值2

这在单线程下是没有问题的,但是多线程就有问题了

意思就是排序的前提是执行结果要准确,上面案例两个变量的操作指令顺序发生了变化,但是,最终结果是对的

如果你想并发的情况下,消除因为指令重排导致的一些问题,此时代码就可以改为

volatile int i=1;
boolean flag=true;
i=2;
flag=false;

此时,前三行代码编译后的字节码范围内的指令,是不能够进行重排序的,所以,flag=false指令一定是最后执行

案例二:

-------thread1-------------
obj=createObj()
init=true

上面2行是线程1执行的,下面是线程2执行的
------------thread2-------------

while(!init){
     sleep();
}
 useobj()

以上代码的意思是 线程1创建完obj后,赋值init为true,表示obj创建成功,然后线程2在循环判断init是不是true,如果不是true,则一直睡,如果是true,则使用obj。假如
obj=createObj() 执行了10秒,后执行init=true。但是此时若发生指令重排序,init=true 先执行了,然后再执行obj=createObj(),那此时线程2的逻辑就错了,判断的时候,init是true,但是obj此时还没有创建出来

所以第二个案例的优化方案就是给obj变量加上volatile修饰即可

比较volatile锁和sync锁

并发同步锁,sync保证了读写双同步,而volatile只保证了读同步,写不同步,正因为写不同步,所以不能保证原子性
也正因为如此,在大概率的情况下,volatile锁的性能优越于sync锁

使用场景:
由于volatile变量只能保证可见性,在不符合以下两条规则的运算场景中,我们仍然要通过加锁来保证原子性。
运算结果并不依赖变量的当前值(比如 setValue() 方法不依赖当前值,++ 操作符则依赖当前值),或者能够确保只有单一的线程修改变量的值。
变量不需要与其他的状态变量共同参与不变约束。

我的语言整理:
当一个变量在并发的场景中起到了作用,但是了,在这些并发的线程中,只有一个线程可以修改它的值,其他线程只能读取这个值,于是,加上volatile,实现变量值的同步性,当变量值发生变化的时候,所有的线程都可以立即知晓最新结果。同时,由于这个变量值的前后代码的执行顺序不同,可能导致其他线程执行逻辑出错,于是,用volatile禁止指令重排的优化操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值