java关键主要代码,万万没想到 Java 中最重要的关键字竟然是这个!

volatile关键字在多线程环境下确保内存可见性和防止指令重排序。它强制将副线程的内存更新到主内存,保证每个线程获取到最新值,避免加锁导致的上下文切换。文章探讨了指令重排序的概念,以及volatile如何通过内存屏障来防止重排序,保证原子性。
摘要由CSDN通过智能技术生成

以下文章来源于小明菜市场 ,作者小明菜市场

article.php?pk=5fb360938e9f093f1e3710fc&f=zaker_live

作者   |   小明菜市场

来源   | 小明菜市场(ID:fileGeek)

头图   |    CSDN   下载自东方 IC

volatile 关键字主要是用于指令重排序,常常用于保证内存的可见性和防止指令重排序。

内存可见性是指所有线程都能看到共享内存的最新的状态。例如,在多线程环境中,加上 volatile 关键字以后,每个线程的内存会强制刷新到主内存中,实现每个线程都保证其关键字内存是最新的。

举一个失效的代码

public class MutableInteger { private int value; public int get ( ) { return value; } public void set ( int value ) { this.value = value; }}

这份代码,在多线程环境下,是正常运行的,但是在非多线程环境下属于不正常运行的,因为 get 和 set 方法没有添加同步锁,如果线程一调用 set 方法,那么正在调用的 get 方法的线程二,可能会看到前值,也可能会看到后值。

解决办法相当的简单,直接加上 volatile 关键字。

private volatile int value;

在上方代码中,加上 volatile 关键字以后,所有副线程的关键字的内存,会强制刷新到主线程中,实现每个线程中的变量关键字都能实时的获取到最新值。相当于给 get 和 set 方法加锁。

java 变量的读写主要分为以下几个关键字进行变量的读写。lock 把线程标识为独占状态。unlock 解除独占状态 read 从主内存传输到工作内存 load 装载进入工作内存 use 把工作内存的值传递给执行引擎 assign 回传工作内存的值 store 把工作内存的值回传给主内存 write 把 store 操作的值回传给主内存中

通过 read load use 三个关键字连续出现,以及,assign,store,write 这三个关键字连续出现,保证原子性。其控制如下图所示

article.php?pk=5fb360938e9f093f1e3710fc&f=zaker_live

注意:volatile 关键字是一种非锁机制,这种机制可以避免锁引起的上下文的切换

1、什么是指令重排序

在虚拟机层面,为了尽可能的减少内存操作速度远远慢于 CPU 运行速度带来的 CPU 空置的问题,虚拟机会按照一定的规则把编译后的 class 文件进行打乱。

在硬件层面,CPU 会把接受到的程序,和一批指令按照一定的规则进行从排序,同样是缓存和 CPU 速度的问题。

被 volatile 关键字修饰的变量,会在之前添加一个 lock 汇编指令,用于强制防止指令从排序。

2、如何禁止

通过内存屏障实现,内存屏障分为 写屏障,读屏障,读写屏障。

编译器,在编译器层面,在编译器层面会对指令进行从排序,添加了 volatile 关键字以后会对指令进行从排序,这样可以显示的告知编译器应该避免生成的代码违背预期。

机器相关:在多核机器下,由于程序是多线程运行的,操作系统,直接调用 CPU 所实现的内存屏障,在硬件层面,实现其原子性操作。

更多精彩推荐

点分享

点点赞

点在看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值