33、volatile

在实际项目使用并不多,但是容易出错。很多人感觉和synchronized差不多,实际上完全不一样。我们看一下两者的区别:

volatile保证程序的可见性,这个和synchronize的区别就非常大,首先volatile他并不保证原子性。synchronized可以保证原子性,

什么叫原子性呢? 就是多个线程同时操作一个数据或则方法时,他们没有办法同时操作,只有一个操作完毕,另一个才能操作。

什么是可见性呢?线程在访问这样一个变量的时候,他都会去读取最新的值,即便被其他线程修改了。

volatile保证可见性,他的实现原理:内存直读,禁止指令重排序。

内存直读就是每次都从内存中读取,不会走任何的缓存。这样可以保证每次读到的都是新的。

因为变量发生变化的时候,就是内存对应某个地址的值发生变化,不管任何线程去操作,每次都从内存地址里面去读出来的数肯定是在这个时刻最新的值。

那什么情况下会发生读到老的数据呢

cpu有自己的缓存和寄存器,从内存中拿到数据,然后放到缓存或则寄存器里面处理,这样就有一个时间差。

比如我们有一个数据在没有读到cpu缓存之前就有其他线程来读取,那么他读取到的是什么呢?是缓存中老的值,还没有同步。

非volatile是从缓存里面读,读了再执行,可能被修改

volatile变量直接去内存里面找。保证每次都读最新的。

 

禁止重排序

首先我们看下什么是cpu指令的重排序,cpu允许将多条指令,不按照程序规定的顺序来执行。我们知道cpu执行会把多条指令进行一定的优化,把他拆成若干块,然后把各部分发给相应的电路单元来处理。A=B B=C c=A  A=B B=C  其实cpu只执行两句  A=b  b=c  其他的可能会被优化掉  

比如,我们new 一个对象,你认为先分配一个块内存地址,再去new 对象,有可能是找到一块缓存区,先构造了一个对象,然后在分配地址,然后在分配指向。和我们想的不一样。

禁止重排序就是,在读取地址内容的时候,在最后增加了一句,内存屏障,他告诉cpu,不允许把这后面内存排到他之前。保证了前面都是有序的。

synchronized 

既可以保证可见性,又能够保证原子性。

可见性体现在:通过synchronized或者Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存中。

原子性表现在:要么不执行,要么执行到底。

虽然效率比synchronized高,但是容易出粗,不好排查错误,但是不推荐使用。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值