volatile 关键字和多处理器总线嗅探

博客介绍了volatile变量修饰的共享变量写操作会多出含Lock前缀的汇编指令,在多核处理器下会将当前处理器缓存行数据写回系统内存,并使其他CPU缓存的该内存地址数据无效。还提到多处理器总线嗅探及缓存一致性协议,且编译器不会对volatile读写前后的内存操作重排序。

volatile变量修饰的共享变量在进行写操作的时候回多出一行汇编:

0x01a3de1d:movb $0×0,0×1104800(%esi);0x01a3de24:lock addl $0×0,(%esp);

Lock前缀的指令在多核处理器下会引发两件事情。

1)将当前处理器缓存行的数据写回到系统内存。

2)这个写回内存的操作会使其他cpu里缓存了该内存地址的数据无效。

多处理器总线嗅探:

       为了提高处理速度,处理器不直接和内存进行通信,而是先将系统内存的数据读到内部缓存后再进行操作,但操作不知道何时会写到内存。如果对声明了volatile的变量进行写操作,JVM就会想处理器发送一条lock前缀的指令,将这个变量所在缓存行的数据写回到系统内存。但是在多处理器下,为了保证各个处理器的缓存是一致的,就会实现缓存缓存一致性协议,每个处理器通过嗅探在总线上传播的数据来检查自己的缓存值是不是过期了,如果处理器发现自己缓存行对应的内存地址呗修改,就会将当前处理器的缓存行设置无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据库读到处理器缓存中。

编译器不会对volatile读后面的任意内存操作重排序;

编译器不会对volatile写前面的任意内存操作重排序;

volatile关键字的原理主要体现在两个重要方面,即保证可见性一定的有序性。 ### 可见性原理 在多线程环境中,每个线程都有自己的工作内存,变量在主内存中存储。线程对变量的操作会先从主内存拷贝到工作内存,操作完成后再写回主内存。如果没有volatile关键字,一个线程对变量的修改可能不会及时刷新到主内存,其他线程也无法及时获取到最新值,从而导致内存缓存数据不一致错误 [^5]。 基于CPU缓存一致性协议,JVM实现了volatile的可见性。当一个变量被声明为volatile时,线程对该变量的写操作会立即刷新到主内存,而读操作会直接从主内存读取最新值。例如,当一个线程修改了volatile变量的值,它会强制将该变量的最新值刷新到主内存,同时其他线程在读取该变量时,会使自己工作内存中该变量的缓存失效,从而重新从主内存中读取最新值 [^4]。 ### 有序性原理 在Java中,为了提高性能,编译器处理器会对指令进行重排序。重排序可能会导致程序在多线程环境下出现问题。volatile关键字可以禁止指令重排序,保证一定的有序性。 volatile关键字通过内存屏障来实现禁止指令重排序。内存屏障是一种特殊的指令,它可以确保在屏障之前的指令不会被重排序到屏障之后,反之亦然。当一个变量被声明为volatile时,在对该变量进行写操作之前会插入一个写屏障,保证写操作之前的所有操作都已经完成并刷新到主内存;在对该变量进行读操作之后会插入一个读屏障,保证读操作之后的所有操作都在读取到最新值之后才会执行。 ### 原子性问题 需要注意的是,volatile无法保证操作的原子性。例如,对于变量的自增操作(i++),它实际上包含了三个操作:读取变量的值、对值进行加1操作、将新值写回变量。volatile不能保证这三个操作是具有原子性的,可以通过AtomicInteger或者Synchronized来保证这类操作的原子性 [^3]。 ### 总线风暴问题 由于总线嗅探机制,使用volatile关键字时,线程会不断监听总线。如果大量使用volatile关键字,会引起总线风暴,导致系统性能下降。所以,volatile关键字的使用要适合具体场景 [^4]。 ```java // 示例代码,展示volatile的可见性 class VolatileExample { // 使用volatile关键字声明变量 volatile boolean flag = false; public void writer() { // 修改volatile变量的值 flag = true; } public void reader() { // 读取volatile变量的值 while (!flag) { // 等待flag变为true } System.out.println("Flag is now true"); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码海无涯苦做舟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值