java volatile关键字的作用_Java并发编程彻底搞懂volatile关键字「建议收藏」
大家好,又见面了,我是你们的朋友全栈君。
背景
Java线程控制中常用的两个关键字:synchronized、volatile
因上篇文章《程序员眼中的Synchronized同步锁》对synchronized关键字进行来详解。本篇文章主要对volatile关键字进行解剖。
volatile关键字特性
内存可见性(Memory Visibility),所有线程都能看到共享内存的最新状态;有序性;不具备原子性(最致命缺点)。volatile解决什么样的问题?
同步死循环
P ri n t S t ri n g
Run方法
说明:上述代码当程序运行在-server服务器模式中64bit的JVM上时,会出现死循环。解决办法是使用volatile关键字。
关键字volatile的作用是强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量值。
异步死循环在谈异步死循环前,我们先看如下代码:
Ru n T h re a d
Run方法
说明:上述代码当程序运行在-server服务器模式中64bit的JVM上时,同样会出现死循环。
分析为什么会出现这种情况?
在启动RunThread线程时,变量isRunning == true;存在于公共堆栈及线程的私有堆栈中。在JVM被设置为-server模式时为了线程运行的效率,线程一直在私有堆栈中取得isRunning的值时true。而代码thread.setRunning(false);虽然被执行,更新的却是公共堆栈中的isRunning变量的值fals,所以一直就是死循环的状态。内存结构图如下:
线程私有堆栈图
上述问题解决方案其实很简单,跟同步死循环解决方案一致使用volatile关键字,其内存结构如下:
读取公共内存
volatile为什么不具备原子性?一张图看懂变量在内存中的工作流程。
变量在内存中工作流程
read和load阶段,从主存复制变量到当前线程工作内存;use和assign阶段,执行代码,改变共享变量值;store和write阶段,用工作内存数据刷新注册对应变量值。说明:在多线程环境中,use和assign是多次出现的,但这一操作并不是原子性,也就是read和load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,也就是私有内存和公共内存中的变量不同步,所以计算时结果和预期不一致,也就出现线程安全问题。
对于volatile修饰的变量,JVM虚拟机只是保证从主内存加载到线程工作内存的值是最新的;因此volatile关键字解决的是变量【读】时的可见性问题,但无法保证原子性,对于多个线程访问同一个实例变量时需要进行【加锁】同步。
总结
volatile和synchronized两者之间比较:
关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好;volatile只能修饰变量,而synchronized可以修饰方法、代码块等。多线程访问volatile不会发生阻塞,而synchronized会出现阻塞。volatile能保证数据的可见性,但不能保证数据的原子性;而synchronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存和公共内存中的数据做同步处理。关键字volatile解决的是变量在多个线程之间的可见性;而synchronized关键字解决的是多个线程之间访问资源的同步性。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/138498.html原文链接:https://javaforall.cn
相关文章
- java二维数组试题_Java二维数组及习题总结
- java源程序文件扩展名_JAVA源代码的扩展名为( )
- java.util.scanner sc_Java的Scanner sc=new Scanner(System.in)是什么意思「建议收藏」
- JAVA的使用_Java集成开发环境
- Java的juc并发编程包
- 动手体验 ES 8.4.x 实时监控 Java 应用运行状态
- 【Java 并发编程】CountDownLatch 简介
- java并发编程(九)
- JAVA多线程高并发学习笔记(三)——Callable、Future和FutureTask详解编程语言
- Java并发编程:Callable、Future和FutureTask详解编程语言
- Java并发编程之volatile关键字解析详解编程语言
- Java并发编程:线程池的使用详解编程语言
- java和golang并发测试详解编程语言
- Java高效操作MySQL数据库(java写入mysql)
- Linux下配置Java开发环境的指南(linux配置java环境)
- Java并发-不懂原理多吃亏
- Java并发编程视频分享-第一期
- 数据库的操作Java与MySQL搭配:完美数据库操作(java对mysql)
- 实现高并发:Java利用Redis秒杀成功(java秒杀redis)
- 数据库Java编程修改Oracle数据库的实践(java修改oracle)
- 编程玩转Java之Oracle编程实战(java中的oracle)
- Java并发编程示例(七):守护线程的创建和运行