java volatile关键字的作用_Java并发编程彻底搞懂volatile关键字「建议收藏」

java volatile关键字的作用_Java并发编程彻底搞懂volatile关键字「建议收藏」背景Java线程控制中常用的两个关键字:synchronized、volatile因上篇文章《程序员眼中的Synchronized同步锁》对synchronized关键字进行来详解。本篇文章主要对volatile关键字进行解剖。volatile关键字特性内存可见性(MemoryVisibility),所有线程都能看到共享内存的最新状态;有序性;不具备原子性(最致命缺点)。volatile解决什么…

大家好,又见面了,我是你们的朋友全栈君。

背景

Java线程控制中常用的两个关键字:synchronized、volatile

因上篇文章《程序员眼中的Synchronized同步锁》对synchronized关键字进行来详解。本篇文章主要对volatile关键字进行解剖。

volatile关键字特性

内存可见性(Memory Visibility),所有线程都能看到共享内存的最新状态;有序性;不具备原子性(最致命缺点)。volatile解决什么样的问题?

同步死循环

5fa4ce9fbbf51b9040db7626e85794e1.pngP ri n t S t ri n g

f1167328122190c8d46e3271063fabb3.pngRun方法

说明:上述代码当程序运行在-server服务器模式中64bit的JVM上时,会出现死循环。解决办法是使用volatile关键字。

关键字volatile的作用是强制从公共堆栈中取得变量的值,而不是从线程私有数据栈中取得变量值。

异步死循环在谈异步死循环前,我们先看如下代码:

e1d62619e104a9b0b3d56729c6c9f119.pngRu n T h re a d

e9beb7920108b7778986efaa1fa5bf2b.pngRun方法

说明:上述代码当程序运行在-server服务器模式中64bit的JVM上时,同样会出现死循环。

分析为什么会出现这种情况?

在启动RunThread线程时,变量isRunning == true;存在于公共堆栈及线程的私有堆栈中。在JVM被设置为-server模式时为了线程运行的效率,线程一直在私有堆栈中取得isRunning的值时true。而代码thread.setRunning(false);虽然被执行,更新的却是公共堆栈中的isRunning变量的值fals,所以一直就是死循环的状态。内存结构图如下:

8dfba7756bc5c67ed26fa3391476a0bc.png线程私有堆栈图

上述问题解决方案其实很简单,跟同步死循环解决方案一致使用volatile关键字,其内存结构如下:

036701b3841513f714c300a0848da666.png读取公共内存

volatile为什么不具备原子性?一张图看懂变量在内存中的工作流程。

cad9ae9c7dcfee6514b128f831a651f8.png变量在内存中工作流程

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关键字解决的是多个线程之间访问资源的同步性。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/138498.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • C语言中open函数「建议收藏」

    C语言中open函数「建议收藏」作用:打开和创建文件。  简述:  #include  intopen(constchar*pathname,intoflag,…/*mode_tmode*/);  返回值:成功则返回文件描述符,否则返回-1  对于open函数来说,第三

  • MacBook Pro常用快捷键汇总

    MacBook Pro常用快捷键汇总首先,总结一下Mac快捷键的图形符号:Mac中主要有四个修饰键,分别是Command,Control,Option和Shift。这四个键分别有自己的图案,他们经常出现在Mac应用程序中的菜单栏里,方便你随时学习新的快捷键。基本的快捷键Command是Mac里最重要的修饰键,在大多数情况下相当于Windows下的Ctrl。所以以下最基本操作很好理解:

  • PL/SQL语句_sql语句declare用法

    PL/SQL语句_sql语句declare用法因为SQL只能访问、操作数据库,却不能进行程序设计,而OraclePL/SQL是一种高级数据库程序设计语言,该语言专门用于对ORACLE数据库进行访问,并且可以进行过程处理。*注:在PL/SQL中只能用SQL语句中的DML部分,不能用DDL部分,如果要在PL/SQL中使用DDL(如CREATEtable等)的话,只能以动态的方式来使用。**1.DML(datamanipulationlanguage)数据操纵语言:比如SELECT、UPDATE、INSERT、DELETE

  • Typora——MarkDown学习笔记

    Typora——MarkDown学习笔记一级标题:# 文字二级标题:## 文字三级标题:### 文字字体粗体:文字两边加**斜体:文字两边加*斜体并加粗:文字两边加***删除文字:两边加~~引用:>+空格分割线:— 或者***图片:![截图](图片路径)超链接:点击跳转排序:排序号:1. 2. 3.无序:·回车表格名字性别生日张三男19990513代码:skdsldl…

  • Python保留小数位数和保留有效数字「建议收藏」

    Python保留小数位数和保留有效数字「建议收藏」保留小数位数a=1.23456789保留小数点后3位:’%.3f’%a保留小数点后6位:’%.6f’%a

  • STM32驱动ST7701S芯片(vⅰV0手机换屏价)

    1、配置GPIO口voidLCD_GPIO_Config(void){/*定义一个GPIO_InitTypeDef类型的结构体*/GPIO_InitTypeDefGPIO_InitStructure;/*????IO??*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号