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

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 硬核!SpringBoot连接MySQL数据库,十分钟啃透「建议收藏」

    硬核!SpringBoot连接MySQL数据库,十分钟啃透「建议收藏」目录1.pom.xml添加依赖2.application.properties添加数据库配置3.添加实体类4.添加Dao5.添加Controller6.新建数据库7.测试上篇只需两步!Eclipse+Maven快速构建第一个SpringBoot项目已经构建了一个SpringBoot项目,本文在此基础上进行连接MySQL数据库的操作。1.pom.xml添加依赖<dependency><groupId&.

    2022年6月25日
    34
  • Java 多线程(超详细)

    Java 多线程(超详细)多线程学习思路:为什么学习线程?为了解决CPU利用率问题,提高CPU利用率。=》什么是进程?什么是线程?=》怎么创建线程?有哪几种方式?有什么特点?=》分别怎么启动线程?=》多线程带来了数据安全问题,该怎么解决?=》怎么使用synchronized(同步)决解?=》使用同步可能会产生死锁,该怎么决解?=》线程之间是如何通信的?=》线程有返回值吗?该如何拿到?=》怎么才能一次性启动几百上千个的线程?线程的概念什么是进程进程是操作系统中正在执行的不同的应用程序,例如:我

    2022年7月9日
    22
  • 严苛模式(StrictMode)

    严苛模式(StrictMode)

    2021年11月29日
    40
  • linux node 安装_linux查看gcc是否安装

    linux node 安装_linux查看gcc是否安装官方下载:最新版下载地址:http://nodejs.cn/download/v14.3下载地址:https://nodejs.org/download/release/v14.3.0/安装

    2022年10月15日
    3
  • python学习—— IPy 强大的IP地址解析模块

    python学习—— IPy 强大的IP地址解析模块       最近在忙着做计算机网络的课程设计,打算写一个可以扫描内网主机的扫描工具。学习过程中安利到了许多python新姿势,IPy模块就是其中一个。1.IPy模块。       在IP地址规划中,涉及到计算大量的IP地址,包括网段、网络掩码、广播地址、…

    2025年6月23日
    4
  • 服务器显示asp错误,Windows7 IIS+ASP http500内部服务器错误(显示它的本来面目)

    服务器显示asp错误,Windows7 IIS+ASP http500内部服务器错误(显示它的本来面目)在WINDOWS7上安装了iis7.5,调试ASP程序时出现http500内部服务器错误:首先,打开IE选项设置—高级—把“显示友好http错误信息”,可以看到如下错误提示:解决办法是打开将错误送到浏览器”changedthedefaultforthe”scriptErrorSentToBrowser”flaginIIS7”,将选项设置为True.设置方法一:以管理员身份运行CM…

    2022年8月12日
    7

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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