volatile关键字是怎样实现的

理解volatile关键字可以分为两块,一块是它到底是怎么实现功能的,另一部分就是Java内存模型中volatile的内存语义。前者是变量加上volatile之后,处理器和编译器会怎样的处理,后者是在整个Java程序中,添加了volatile之后,编译器会保证volatile这一块不会被重排序。点击查看Java内存模型

Java语言对volatile的定义:Java 编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。volatile又被称为轻量级的synchronized,但是volatile并不需要加锁,它没有线程上下文的切换和调度,比synchronized的使用成本更低。

volatile保证可见性,但是不保证原子性,JMM会防止对volatile的执行重排。

可见性

每个线程都有自己的工作内存(寄存器、高速缓存组成),线程之间是通过主内存进行通信。即线程A把从主内存读取,然后进行运算,将运算后的结果从自己的工作内存写回到主内存,当线程A写回完成之后,其他线程再去主内存读取,就可以得到线程A处理的结果,完成通信。但是,线程A不会经常回写主内存,不然的话处理速度就慢死了,不回写其他的线程就看不到处理之后的数据,只能得到之前的数据。线程看到的数据不一致,就造成可见性问题。

计算机的处理器运行速度要比内存的读取速度快好几个数量级。但是整个运算流程必须是先从内存中读取某个数据,然后交给处理器,随后将结果再写回到内存中。如果这样的话整个运行的速度就会被卡在内存上,内存读取有多快整体运算有多快,就算处理器再好也没用。巧妇难为无米之炊,从内存读取的数据就是处理器需要的米。遇到海量高并发的时候有个统一思想,异步缓存批量处理。这里采用的就是批量处理,直接从内存中读取一批数据,然后统一交给处理器处理,等处理完成之后统一写回到内存中。

所以普通的数据是不会立即写回到主内存中的,而是先保存在工作内存中。但是如果用volatile修饰,会让工作内存立即写回到主内存或者从主内存中重新读取,保证数据的可见性。

Lock前缀

有 volatile 变量修饰的共享变量进行写操作的时候会多出一行汇编代码,且是Lock指令开头。Lock 前缀的指令在多核处理器下会引发了两件事情:
1.将当前处理器缓存行的数据写回到系统内存。
2.这个写回内存的操作会使在其他 CPU 里缓存了该内存地址的数据无效。

Lock前缀指令导致在指令执行期间,声言处理器的LOCK#信号,LOCK#信号会保证在声言此信号期间,处理器可以独占任何共享内存。一部分处理器是通过锁住总线,总线控制读写,锁住总线意味着其他的处理器没有办法访问共享内存,此时只有当前的处理器可以访问内存,实现了独占共享内粗功能。但是锁住总线的代价是很大的,所以另一部分处理器采取的是锁住缓存,如果要写入的内存区域已经缓存在处理器内部,则不会声言LOCK#信号,而是锁定内存区域的缓存并将他写回到内存中,并使用缓存一致性机制来确保修改的原子性,此操作被称为“缓存锁定”,缓存一致性机制会阻止同时修改由两个以上处理器缓存的内存区域数据。

当一个处理器缓存写回到内存时,其他处理器的中此缓存数据将无效。每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是否过期,当处理器发现自己缓存行对应的总线地址被修改,就会将当前处理器的缓存设置为无效,当处理器需要此数据时,会重新从共享内存中读取。

缓存一致性机制:总线加锁是对整个共享内存,此时其他的处理器无法从共享内存读取数据,会严重降低CPU的处理能力。缓存一致性协议只会对单个缓存行的数据进行加锁,不会影响到内存中其数据的读写。缓存一致性协议有:MSI、MESI、MOSI等。MESI协议只对汇编指令中执行加锁操作的变量有效,表现到java中为使用voliate关键字定义变量或使用加锁操作。

MESI协议有四种状态:修改、独占、共享、无效
在这里插入图片描述
大致流程如下:
1.线程A读取数据Q,将数据Q的状态设置为E(独享、互斥),同时通过总线嗅探机制对共享内存中的数据Q进行嗅探

2.线程B再次读取数据Q, 总线嗅探将线程A中的Q设置为S(共享),线程B的Q状态也是S共享

3.线程A修改数据Q, 线程A中的状态变为M(修改),而线程B将会被通知修改为I(无效)。无效的数据将不会被操作,需要从共享内存中重新读取。如果有多个线程同时修改Q,那么总线会进行裁决,某一个变为M,其他的都变为I。

4.线程A将Q回写内存,此时状态变为E(独占),因为只有他时新数据,其他线程都无效,相当都独享。

5.线程B通过总线嗅探机制得知Q已经回写到内存,重新读取Q,状态为S,同时线程A中的状态也变成S。

参考阅读

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值