java volatile可见性解析

java volatile可见性解析很长一段时间中对于volatile关键字都是一知半解的,由于工作中用的比较少,也没有对其深入了解,直到看了《深入理解java虚拟机》之后,才有进一步的了解。   volatile是java虚拟机提供的最轻量级的同步机制,只能作用于变来那个,具备两种特性:保证此变量对所有线程的可见性:可见性是指一旦一个线程修改了此变量的值,其他线程能立即得知。禁止指令的重排序(本文暂不涉及)由于vol

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

      很长一段时间中对于volatile关键字都是一知半解的,由于工作中用的比较少,也没有对其深入了解,直到看了《深入理解java虚拟机》之后,才有进一步的了解。
      volatile是java虚拟机提供的最轻量级的同步机制,只能作用于变来那个,具备两种特性:

  • 保证此变量对所有线程的可见性:可见性是指一旦一个线程修改了此变量的值,其他线程能立即得知。
  • 禁止指令的重排序(本文暂不涉及)

由于volatile的可见性分析是基于java内存模型的,此处对java内存模型做个简单的概述。

java内存模型

主内存和工作内存

  • 主内存:所有的变量都存储在主内存中
  • 工作内存:每条线程都有自己的工作内存,线程的工作内存中保存了被该线程使用到的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,不能直接从主内存中读写变量,不同线程之间也无法访问其他线程工作内存中的变量,线程之间变量值的传递只能通过主内存完成。


线程-主内存-工作内存三者之间的关系






线程-工作内存-主内存三种之间的关系图

java内存间相互操作(八种内存操作指令)

  • 指令功能: 完成主内存和工作内存之间的交互, 主要功能为实现变量从主内存拷贝到工作内存,如何从工作内存同步会主内存
  • 指令详解:
    1. lock(锁定):作用于主内存中的变量,限制该变量为一个线程独占的状态
    2. unlock(解锁):作用于主内存的变量,将变量从一个线程独占的状态中释放出来,释放后的变量才能被其他变量占用。
    3. read(读取):作用主内存的变量,将一个变量从主内存加载到工作内存,以便之后的load操作使用。
    4. load(载入):作用于工作内存,它把read读取的变量值放到工作内存的变量副本中
    5. use(使用):作用于工作内存,把工作内存中的变量的值传递给执行引擎,每当虚拟机遇到需要使用变量的值的字节码指令是会执行此操作
    6. assign(赋值):作用于工作内存,把从执行引擎中接收到的值赋值给工作内存的变量,每当虚拟机遇到给变量赋值的字节码指令是执行此操作
    7. store(存储):作用于工作内存,把工作内存中的变量传送到主内存中,以便之后的write操作使用。
    8. write(写入):作用于主内存,将store操作中传递过来的值存储到主内存变量中。

如何实现volatile的可见性

声明: T为一个线程 V为volatile变量
1. 保证自己所在的线程可见其他线程对变量所作的修改
– 线程T对变量V执行的前一个动作是load的时候,线程T才能对变量V执行use操作,线程T对变量执行的后一个操作是use的时候,线程T才能对变量执行load操作。换句话说,线程T对变量V执行的操作中,read(read和load绑定一起工作), load和use必须绑定在一起。保证了自己所在的线程获取到的变量数据永远是最新的。
2. 保证自己所在线程对变量的修改对其他线程是可见的。
– 线程T对变量V执行的前一个动作是assign的时候,线程T才能对变量V执行store操作,线程T对变量V执行的后一个操作是use的时候,线程T才能对变量V执行assign操作,换句话说,线程T对变来那个V执行的操作中,assign, store,write(store和write一起工作)必须绑定在一起工作,保证了自己所在线程的修改对其他线程来说是可见的。

可见性推论:由上述两条规则可知,当执行引擎想要使用某一个volatile变量的时候,他必须从再次从主内存中读取变量刷新工作内存中的变量值。当执行引擎对某个变量执行完某操作并希望将该变量存入工作内存中时,必须同步将该变量的值同步到主内存中。

volatile不具备线程安全性

  • 从以上的分析中可以得出volatile实现了线程之间的可见性,但是volatile并不具备线程安全的特性。
    原因:以上的可见性分析只是针对单个线程而言的,但是当两个线程分别对同一个变量V执行read操作,并对读取后的变量执行相关的运算,之后两个线程会将自己操作的变量同步会主内存,这时候就会存在后同步到操作会覆盖前一个同步到操作。

总结:volatile关键字保证了不同线程对变量的修改对于其他线程来说是立即可见的,但volatile并不具备线程同步到特性!

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

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

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


相关推荐

  • python怎么匹配字符串_python正则表达式如何匹配字符串

    python怎么匹配字符串_python正则表达式如何匹配字符串python 正则表达式匹配字符串的方法 1 使用 这个正则表达式来提取单个位置的字符串 2 使用 P 这个正则表达式 匹配连续多个位置的字符串 python 正则表达式匹配字符串的方法 一 单个位置的字符串提取这种情况我们可以使用 这个正则表达式来提取 举例 一个字符串 a123b 如果我们想提取 ab 之间的值 123 可以使用 findall 配合正则表达式 这样会返回一个

    2025年8月11日
    0
  • opencv-形态处理

    opencv-形态处理

    2022年1月10日
    41
  • [C#] 剖析 AssemblyInfo.cs – 了解常用的特性 Attribute

    [C#] 剖析 AssemblyInfo.cs – 了解常用的特性 Attribute剖析 AssemblyInfo.cs-了解常用的特性Attribute【博主】反骨仔【原文】http://www.cnblogs.com/liqingwen/p/5944391.h

    2022年7月2日
    24
  • 电商后台管理系统项目介绍和项目初始化

    电商后台管理系统项目介绍和项目初始化目录一电商项目基本业务概述二电商后台管理系统功能三电商后台管理系统的开发模式(前后端分离)四电商后台管理系统的技术选型五前端项目初始化步骤六创建新项目七安装element-UI插件八配置element-UI为按需导入九安装axios十码云上创建vue_shop仓库,将初始化项目托管到码云一电商项目基本业务概述根据不同的应用场景,电商系统一般都提供了PC端、移动APP、移动Web、微信小程序等多种终端访问方式。二电商后…

    2022年6月4日
    43
  • word文档页码不连续编号怎么办_怎样给论文加页码

    word文档页码不连续编号怎么办_怎样给论文加页码论文页码设置大家好!今天和大家分享两个和页码有关的技巧:大家好!今天和大家分享两个和页码有关的技巧:为分栏页面分别设置页码对纵向文档中的横向表格设置页码page域及域代码操作基础技巧01分栏页面像下面这个文档,对页面分成了两栏,如果现在想给每一栏都添加一个页码序号,也就是在第1页的左右两栏分别显示第1页和第2页,在第2页的左右两栏分别显示第3页和第4页,这样的效果该如何设置呢?我们先在页脚中设置好…

    2025年7月29日
    3
  • rabbitmq集群搭建「建议收藏」

    rabbitmq集群搭建「建议收藏」一、基础安装前提:三个节点都主机映射,关防火墙网络,配好yum(后边出错,主机名和映射要对应)1.安装(三个节点)2.mq1启动rabbitmq服务查看状态3.配置界面访问4.使用界面查看(端口15672,默认帐户和密码guest)二、配置rabbitmq集群服务1.先构建erlang集群①复制cookie认证②配置节点加入集群(顺序很重要,解决报错看)123的顺序停止321的顺序启动rabbitmq服务

    2025年10月25日
    3

发表回复

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

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