Java volatile关键字详解
Java volatile关键字详解
volatile是java中的一个关键字,用于修饰变量。被此关键修饰的变量可以禁止对此变量操作的指令进行重排,还有保持内存的可见性。
简言之它的作用就是:
- 禁止指令重排
- 保持内存的可见性
禁止指令重排
CPU在执行代码时,为了提高执行效率,有时会将代码乱序执行。但是乱序也不是随随便便的乱序,而是在一定规则下,对指令进行重排然后执行。指令重排在单线程下没有什么问题,但是在多线程环境下容易造成并发安全问题。
保持内存的可见性
何谓之内存的可见性,其实笔者在Java线程安全问题一文中对此问题进行过阐述。线程是一种资源,线程在执行代码时有自己的工作内存(线程执行的堆栈)。一般来说,一些共享变量存在于堆内存中,线程对于共享变量的操作实际上对自己工作内存中共享变量的副本进行操作,线程并不会直接操作堆内存的中的共享变量。

这里我们可以通过字节码进行验证,首先我们的java源代码是对变量a进行一个自增操作 => a++,而其对应的字节码为:
getstatic #2
iconst_1
iadd
putstatic #2
return
从字节码层面可以体现出工作内存与主存。但是,Java内存可见性的控制并不是在字节码层面,而是在JVM层面。即使你对变量a使用volatile修饰,那么编译之后的字节码也没有变化。
JVM定义了对于内存的8种操作:

这些操作是JVM层面的操作,在Java源代码中并不能感受到。线程在所操作的共享变量,其实是存在于自己线程栈中的变量副本。在多线程并发的情况下,如果有其他线程修改了主存中的值,那么其他线程无法感知这种修改。因为线程在通过READ-LOAD操作拷贝完副本之后,之后线程对于数据的操作都是对于副本进行的。这也就是内存可见性的问题的来源,简言之就是线程之间无法感知对于主存共享变量的修改。
volatile关键字就是解决了这样的问题,使得线程对于主存具有一定的可见性。其解决方案是对于volatile标注的变量,每次在使用之前都要重新从主存中加载,同时每次对于变量完成修改后,要及时的将变量写回主存。

通过这样的操作,每个线程就能感知到内存中变量的变化,并及时更新自己副本的值。不过需要注意的是,volatile关键字并不能保障并发的安全性。尽管每次在使用之前都会更新值,但是这并没有解决变量访问的有序性。所以在高并发场景下依然会出现问题。
Java volatile关键字详解的更多相关文章
- Java Volatile 关键字详解
原文链接:https://www.cnblogs.com/zhengbin/p/5654805.html 一.基本概念 先补充一下概念:Java 内存模型中的可见性.原子性和有序性. 可见性: 可见性 ...
- Java synchronized 关键字详解
Java synchronized 关键字详解 前置技能点 进程和线程的概念 线程创建方式 线程的状态状态转换 线程安全的概念 synchronized 关键字的几种用法 修饰非静态成员方法 sync ...
- Java之先行发生原则与volatile关键字详解
volatile关键字可以说是Java虚拟机提供的最轻量级的同步机制,但是它并不容易完全被正确.完整地理解,以至于许多程序员都习惯不去使用它,遇到需要处理多线程数据竞争问题的时候一律使用synchro ...
- Java并发编程:JMM (Java内存模型) 以及与volatile关键字详解
目录 计算机系统的一致性 Java内存模型 内存模型的3个重要特征 原子性 可见性 有序性 指令重排序 volatile关键字 保证可见性和防止指令重排 不能保证原子性 计算机系统的一致性 在现代计算 ...
- Java多线程-----volatile关键字详解
volatile原理 Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程.当把变量声明为volatile类型后, 编译器与运行时都会注意 ...
- Java中Volatile关键字详解 (转自郑州的文武)
java中volatile关键字的含义:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html 一.基本概念 先补充一下概念:J ...
- jvm运行机制和volatile关键字详解
参考https://www.cnblogs.com/dolphin0520/p/3920373.html JVM启动流程 1.java虚拟机启动的命令是通过java +xxx(类名,这个类中要有mai ...
- volatile关键字详解
本文系转载,原文链接:http://www.cnblogs.com/Chase/archive/2010/07/05/1771700.html,如有侵权,请联系我:534624117@qq.com 引 ...
- C/C++中volatile关键字详解 (转)
1. 为什么用volatile? C/C++ 中的 volatile 关键字和 const 对应,用来修饰变量,通常用于建立语言级别的 memory barrier.这是 BS 在 "The ...
随机推荐
- 【一天一个基础系列】- java之泛型篇
简介 说起各种高级语言,不得不谈泛型,当我们在使用java集合的时候,会发现集合有个缺点:把一个对象"丢进"集合之后,集合就会"忘记"这个对象的数据类型,当再次 ...
- 【转】Kubernetes scheduler学习笔记
简介 Kubernetes是一个强大的编排工具,可以用来很方便的管理许多台机器,为了使机器的资源利用率提高,同时也尽可能的把压力分摊到各个机器上,这个职责就是由scheduler来完成的. Kuber ...
- Xtrabackup 物理备份
目录 Xtrabackup 安装 Xtrabackup 备份介绍 Xtrabackup全量备份 准备备份目录 全量备份 查看全量备份内容 Xtrabackup 全量备份恢复数据 删除所有数据库 停止数 ...
- C# 类 (11) - Const
Const variable 变量 ,值可变的constant 常量,不可变,C# 里关键字是const当我们定义一个常量的时候,需要立马赋值,以后不能再改这个量了我们可以把常量定义在 method ...
- 多线程(二)多线程的基本原理+Synchronized
由一个问题引发的思考 线程的合理使用能够提升程序的处理性能,主要有两个方面, 第一个是能够利用多核 cpu 以及超线程技术来实现线程的并行执行: 第二个是线程的异步化执行相比于同步执行来说,异步执行能 ...
- docker-compose -----单机多容器管理
Compose是用于定义和运行多容器Docker应用程序的工具.通过Compose,您可以使用YAML文件来配置应用程序的服务.然后,使用一个命令,就可以从配置中创建并启动所有服务. Docker-C ...
- you don't know github
you don't know GitHub <!DOCTYPE html> <html lang="en"> <head> <meta c ...
- 如何使用 js 扩展 prototype 方法
如何使用 js 扩展 prototype 方法 expand prototype function enhancedLog(msg = ``) { // this.msg = msg; enhance ...
- How to get a DOM element's ::before content with JavaScript?
How to get a DOM element's ::before content with JavaScript? https://stackoverflow.com/questions/443 ...
- css picture
css picture https://github.com/cyanharlow https://diana-adrianne.com/ demo https://github.com/cyanha ...