内存屏障以及volatile

什么是内存屏障:

什么是内存屏障
Java中的内存屏障是一种CPU指令, 也是同步机制实现的依赖。内存屏障用于确保多线程环境下的内存可见性和操作的有序性,它是实现线程同步和避免并发问题的关键手段.它可以防止CPU对指令序列进行重排序,从而保证在代码执行过程中,对内存的读写操作按照程序员的意愿来进行

内存屏障通过在代码中插入同步指令来强制线程在特定的位置进行同步,从而解决了多线程环境下的内存可见性和有序性问题。在Java中,常见的内存屏障包括LoadLoad屏障、StoreStore屏障、LoadStore屏障和StoreLoad屏障。这些内存屏障用于限制编译器和处理器在对内存访问进行重排的时机,从而保证程序的正确性。


内存屏障有几种:

  1. LoadLoad
  2. LoadStore
  3. StoreStore
  4. StoreLoad

什么情况会触发内存屏障:

  1. volatile关键字:使用volatile关键字修饰的变量在读写操作时会插入相应的内存屏障,保证了对该变量的操作在多线程环境下的可见性和有序性。
  2. synchronized关键字:进入synchronized代码块或方法会触发一个内存屏障,从而保证进入和退出同步块时的内存可见性和有序性。
  3. Lock接口:Lock接口的实现类(如ReentrantLock)也会在进入和退出锁定的区域时触发内存屏障,确保线程间的同步和正确的内存访问顺序
    当然除了上述场景外 线程的某些方法也会触发内存屏障 比如说Thread.start 和 Thread.join 方法

内存屏障触发会有什么影响:

  1. 内存可见性:内存屏障可以确保在内存屏障之前的所有写操作都对其他线程可见。这意味着一个线程在内存屏障之前对共享变量的修改会立即对其他线程可见,其他线程可以看到这个修改后的值。
  2. 指令重排:内存屏障可以阻止编译器和处理器在内存屏障之前和之后对内存访问进行重排。这样可以保证指令执行的顺序符合程序的预期顺序,防止由于重排导致的并发问题。
  3. 缓存一致性:内存屏障可以确保在内存屏障之前的写操作会刷新到主内存,并在之后的读操作中从主内存加载最新的值。这样可以避免由于处理器缓存数据而导致的线程之间的数据不一致。

volatile如何禁止的指令重排

为了保证volatile变量的禁止指令重排序,Java会在生成的字节码中插入内存屏障(见高亮块下方)来实现

volatile变量的内存屏障是通过一组指令来实现的,包括

  1. LoadLoad: 确保在读取一个volatile变量前,前面的所有读操作都已完成
  2. LoadStore: 确保在读取一个volatile变量后,后面的所有写操作都还没有开始
  3. StoreStore: 确保在写入一个volatile变量前,前面的所有写操作都已经完成
  4. StoreLoad: 确保在写入一个volatile变量后,后面的所有读操作都还没有开始

当一个线程执行一个读取volatile变量的操作时,Java会插入LoadLoad和LoadStore屏障。LoadLoad屏障会防止该读取操作和前面的任何读操作被重排序,LoadStore屏障则会防止该读取操作和后续的写入操作被重排序
当一个线程执行一个写入volatile变量的操作时,Java会插入StoreStore和StoreLoad屏障。StoreStore屏障会防止该写入操作和前面的任何写入操作被重排序,StoreLoad屏障则会防止该写入操作和后续的读取操作被重排序
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值