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并不具备线程同步到特性!

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

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

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

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

(0)
blank

相关推荐

  • 安装matplotlib模块「建议收藏」

    安装matplotlib模块「建议收藏」matplotlib是python中强大的画图模块。首先确保已经安装python,然后用pip来安装matplotlib模块。进入到cmd窗口下,执行python-mpipinstall-Upipsetuptools进行升级。接着键入python-mpipinstallmatplotlib进行自动的安装,系统会自动下载安装包。安装完成后,可以用python-mpip…

  • MongoDB启动失败原因「建议收藏」

    MongoDB启动失败原因「建议收藏」MongoDB启动失败原因今天某个项目突然登录不了,查看服务器发现是后端出现异常,停掉后端重新启动的时候失败,显示是数据库连接失败,然后接着查看数据库,发现数据库连接失败,原因是数据库挂掉了。数据库用的是MongoDB,我也只是听过还没有使用过,简单的在网上查询了一下MongoDB的启动命令就直接开始启动了,结果发现启动失败。尝试了好一些方法后才终于成功启动:尝试提升MongoDB所在文…

    2022年10月30日
  • 钱柜 自助餐_常熟钱柜KTV是不是有自助餐

    钱柜 自助餐_常熟钱柜KTV是不是有自助餐今天去白石桥钱柜K歌,昔日的钱柜看来确实已老也。之前Javor就说钱柜条件越来越差,亲身体会果然不是一般的差。包房的设施很陈旧,点歌系统土到火星,什么按歌星姓名字数点歌,完全不具操作性。音响还勉强,电

  • leetcode题目分类_最长前缀匹配例题

    leetcode题目分类_最长前缀匹配例题原题链接编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 “”。示例 1:输入:strs = [“flower”,”flow”,”flight”]输出:”fl”示例 2:输入:strs = [“dog”,”racecar”,”car”]输出:””解释:输入不存在公共前缀。 提示:0 <= strs.length <= 2000 <= strs[i].length <= 200strs[i] 仅由小写英文字母组成题解分

  • 2021年五面蚂蚁,java必背代码入门[通俗易懂]

    2021年五面蚂蚁,java必背代码入门[通俗易懂]一面(个人感觉回答得还不错)1.自我介绍2.说项目,项目问的非常深(本人提到之前做过的一篇关于FULLGC的问题定位和优化的项目以及一个多并发的项目)2.1对于自己产于过项目的系统定位是否清楚?2.2对于系统的各个模块是否清楚?2.3每个接口的tps?2.4对于上下游系统的依赖?2.5对于使用到的中间件、框架是否清楚?3.你觉得你做的项目中最有亮点的事情?4.memcacheredis同类中间的差异、优缺点?使用注意点有哪些?memcache可以存储的

  • 【面试篇】SpringMVC工作流程「建议收藏」

    【面试篇】SpringMVC工作流程「建议收藏」基础介绍SpringMVC主要是通过前端控制器controller中的注解来完成请求处理的。前段请求从web.xml中servlet的配置开始,根据servlet拦截的url-parttern,来进行请求转发控制。处理请求的流程首先用户发送请求————>前端控制器,前端控制器根据请求信息(如URL)来决定选择哪一个页面控制器进行处理并把请求委托给它,即以前的控制器的控制逻辑部分;页面控制器接收到请求后,进行功能处理,首先需要收集和绑定请求参数到一个对象,这个对象在SpringWeb

发表回复

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

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