JAVA内存屏障

本文介绍了JAVA内存屏障的概念及其在多线程并发中的作用,探讨了synchronized和volatile关键字如何确保内存可见性和有序性。同时,文章指出volatile无法保证原子性,以自增操作为例,解释了并发执行时可能出现的问题。
摘要由CSDN通过智能技术生成

指令重排序

程序在运行时内存实际的访问顺序和程序代码编写的访问顺序不一定一致,这就是内存乱序访问。内存乱序访问行为出现的理由是为了提升程序运行时的性能。这种内存乱序问题主要是由两种原因引起的:

  • 1.写内存屏障(Store Memory Barrier): 在指令后插入Store Barrier, 能让写入缓存中的最新数据更新写入主内存, 让其他线程可见强制写入主内存, 这种显示调用, CPU就不会因为性能考虑而进行指令重排。

  • 2.读内存屏障(Load Memory Barrier): 在指令前插入Load Barrier, 可以让高速缓存中的数据失效, 强制从新从主内存读取数据强制读取主内存内容, 让CPU缓存和主内存保持一致, 避免了缓存导致的一致性问题。

什么是内存屏障

内存屏障(Memory Barrier)与内存栅栏(Memory Fence)是同一个概念,不同的叫法。

内存屏障(memory barrier)是一个CPU指令。该指令可以确保一些特定操作执行的顺序 影响一些数据的可见性(可能是某些指令执行后的结果)。为了禁止编译器和CPU对代码进行重排序,在编译器和CPU层面上都有对应的指令。
作用

  • 强制cpu将store buffer中的内容写入到cacheline中

  • 强制cpu将invalidate queue中的请求处理完毕
    类型

  • 内存屏障是为了解决在cacheline上的操作重排序问题。

    • 编译器在编译时进行了编译优化,导致指令重排;
    • 在多cpu环境下,为了尽可能地避免处理器访问主内存的时间开销,处理器大多会利用缓存(cache)以提高性能。在这种模型下会存在一个现象,即缓存中的数据与主内存的数据并不是实时同步的,各CPU(或CPU核心)间缓存的数据也不是实时同步的。这导致在同一个时间点,各CPU所看到同一内存地址的数据的值可能是不一致的。从程序的视角来看,就是在同一个时间点,各个线程所看到的共享变量的值可能是不一致的。

内存屏障可以被分为以下几种类型
Store:将处理器缓存的数据刷新到内存中。
Load:将内存存储的数据拷贝到处理器的缓存中。

  • LoadLoad屏障:对于这样的语句Load1; LoadLoad; Load2,在Load2及后续读取操作要读取
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值