说说volitile关键字

volitile关键字主要是维护多线程并发环境下类属性值的可见性和代码的有序性。多线程环境下,一个线程在对一个类的属性的值进行修改的时候,其它线程不能立即看到被修改的最新的值是因为在对cpu进行性能优化时引入了高速缓存的概念,CPU本身的运算速度要比内存IO速度要快的多,这就导致在等待内存返回数据的过程中cpu处于阻塞状态,这种阻塞状态是对cpu资源的一种浪费,解决这个问题的方法就是cpu读取数据时先从缓存里面读取,缓存里没有数据再从内存中读取并写入缓存。此时如果一个变量的值同时被缓存在两个CPU即CPU0和CPU1的高速缓存中,当CPU0修改了这一共享变量的值并同步到主存中,CPU1需要从内存中获取最新的值但获取时机是不确定的,这就会导致缓存一致性问题,解决缓存一致性问题的方法是使用总线锁或缓存锁,缓存锁能够保证缓存一致性是因为其中使用的缓存一致性协议(MESI),MESI表示缓存的四中状态即修改,共享,独占,失效,该协议的核心是修改一个共享的数据时,需要先使其它处于共享状态的缓存失效。除此之外,volitile还使用了内存屏障阻止了指令重排。引起指令重排的原因是当CPU0需要修改一个数据的时候,需要向其它拥有处于共享状态缓存的CPU发送read invalidate命令直到其它CPU给出返回结果时CPU0才能够继续写入,从发送命令到写入内存这段时间,CPU0处于阻塞状态,为了解决这个问题,CPU层面引入了store buffer使上述过程异步执行,当CPU0要修改一个共享数据时先将指令放入store buffer中然后再向其它共享内存发送失效指令,此时CPU0继续其它指令的执行直到其它CPU给出的返回响应的时候再把store buffer的数据移入缓存行然后再写入到内存。这个过程虽然能够提高效率,但是会导致指令重排,针对这个问题,CPU层面又提出了Store Forwarding的优化方案,就是cpu可以直接从store buffer中加载数据。

对齐填充

对齐填充主要是为了解决伪共享的问题。CPU的缓存是由多个缓存行组成的,CPU从缓存中读取数据也是以缓存行为单位,每个缓存行的大小是64个字节,这就导致了当CPU与内存进行交互时写入缓存行的数据除目标数据之外还有其他数据,假设CPU0和CPU1的某个缓存行种都存在x,y,z三个类型的数据,若CPU0需要更新x类型的变量,CPU1需要更新y类型的变量,但是这两个变量存在于同一缓存行中,所以就会存在缓存行竞争,如果CPU0获取了该缓存行的执行权限,那么CPU1中的缓存行就会失效,反之同样,这样来来回回的操作就会影响到性能,这是使用对齐填充就能解决这个问题,所谓对齐填充就是当CPU0读取x类型的变量的时候填满64个字节,这就可以时CPU0的这个缓存行里面只存储x类型的变量,这样虽然会浪费空间,但能够避免因缓存行竞争造成的性能损耗。在java8里面可以用@Contended注解开启对齐填充

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值