深度理解volatile关键字

2023-10-28

Volatile

java中可以把字段声明为volatile的。比如:

public class AtomicInteger extends Number implements java.io.Serializable {
   // volatile变量
   private volatile int value;
}

但是volatile启什么作用呢?

作用

这里先说结论:

  1. volatile关键字是并发编程的时候来保证可见性
  2. 简单讲就是线程A修改完volatile字段,线程B立即来读的话,是能读到最新的值的。

这里面有个问题,就是问什么会有可见性的问题?

CPU多级缓存

CPU为了加快处理数据的速度,加入了缓存,加缓存的原则,依赖于局部性原理:

  1. 时间局部性
    某个数据项被访问后,可能很快会被再次访问的特性。
  2. 空间局部性
    某个数据项被访问后,与其地址相近的数据项可能很快被访问的特性。

我们可以利用局部性原理将计算机的存储器组织成为存储器层次结构

在这里插入图片描述

缓存的最小单位是缓存行(cache line),现在主流的CPU缓存行是 64bytes
Linux 系统可以通过cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size命令查看缓存行大小。
Mac 系统可以通过sysctl hw.cachelinesize查看缓存行的大小。

缓存一致性问题 Cache coherence

cpu缓存模型,其实默认情况下是有问题的,特别是多线程并发运行的时候,导致各个cpu的本地缓存跟主内存没有同步,一个数据在各个地方可能都不一样,就会导致数据的不一致问题。
在这里插入图片描述

缓存一致性协议

这里限于文章篇幅,和突出文章主题,不展开讲了。
一句话就是,现在主流的CPU都是通过MESI协议来解决缓存一致性问题的。

Java怎么实现的?

java规范手册

我们先看一下java规范手册对volatile的描述。
在这里插入图片描述
注意上图中红框框里面的文字,也就是说,java规范里面有个happens-before的原则。规则中约定了哪些动作在实际运行过程中要发生于哪些动作之前。而volatile声明的字段就在happens-before的原则里面。

这是在语言层面做的规约,那么实际JVM中又是怎么实现的呢?

class文件&CPU指令

以hotspot为例,先看一下volatile声明的字段在class文件是什么样子的
添加volatile

int v;
  descriptor: I
  flags:

添加volatile

volatile int v;
  descriptor: I
  flags:ACC_VOLATILE

class文件中变量flags: ACC_VOLATILE

通过 jitwatch 工具查看,运行过程中CPU实际执行的指令是啥呢?
我们发现,加了volatile的变量,在保存的时候
多了一行汇编指令lock addl $0x0,(%rsp)

查询 IA32 手册:

在这里插入图片描述
在这里插入图片描述

简述一下原文的要点:
在执行相应指令时,使处理器的LOCK#信号被激活(将指令转换为原子指令)。在多处理器环境中,LOCK#信号确保在信号被激活期间,处理器独占任何共享内存

限制使用的命令ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, XCHG.

总结下来就是lock前缀指令 + 缓存一致协议来实现的

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深度理解volatile关键字 的相关文章

随机推荐

  • chmod 777 是什么意思

    您正在尝试修复您的Web服务器的权限问题 并在互联网上找到了信息 说您需要递归chmod 777网络目录 在此之前 请确保您了解什么是chmod R 777这样做 以及为什么永远不应该将权限设置为 777 本文解释了基本的 Linux 权限
  • 为什么更推荐使用组合而非继承关系?

    前言 最近在看公司项目的代码 看到了大量的继承体系 而且还是继承了多层 维护 阅读都十分的困难 在查阅了一些资料以后 包括 Effective Java 一书中的第16条提到 组合优先于继承 那继承到底会暴露什么问题呢 为什么更推荐优先使用
  • Arduino搭建盲猜数字小游戏

    1 本文整理自视频 太极创客 零基础入门学用Arduino 第一部分 合辑 需要的硬件 一个Arduino Uno开发板 一个200 500欧姆电阻 一个共阴极数码管 一个按键 数条杜邦线 跳线 2 显示数字其实就是显示各个数码管 注意需要
  • 重温Linux内核:互斥和同步

    文章目录 互斥和同步 1 前言 2 概念 2 1 竞态 2 2 共享资源 临界资源 2 3 造成竞态的根本原因 3 并发分类 解决竞态的方法 4 中断屏蔽 5 原子变量 5 1 定义 5 2 实现原理 5 3 API 5 4 注意事项 6
  • 开发踩坑日常 (parseInt进制转换,文字方向、换行,代理请求,xlsx)

    日常踩坑填坑 js进制转换 刚发现有同学没搞清楚这个 parseInt number 进制数 将任意进制 转换 为十进制 强调一下 第二个参数 是形容第一个参数是什么进制的 并不是转换的目标进制 这里贴一下W3C 的文档说明 https w
  • 【转载】windows和wls文件互通

    windows和wls文件互通 wsl访问windows文件 https www jianshu com p d332e05adb6f windows访问wsl文件 https blog csdn net Caoyang He articl
  • Android 之 WebView (网页视图)基本用法

    本节引言 本节给大家带来的是Android中的一个用于显示网页的控件 WebView 网页视图 现在Android应用 层开发的方向有两种 客户端开发和HTML5移动端开发 所谓的HTML5端就是 HTML5 CSS JS来构建 一个网页版
  • TCPIP技术实验大作业:基于TCP/IP的程序开发技术综述及应用实践

    一 基于TCP IP的程序开发技术综述 1 1TCP IP协议族简介 TCP IP也被称作传输控制协议 网际协议 作为网络互连的核心协议 受到广泛的应用 该协议类型作为开放性的标准应用在各种计算机中 在一定程度上保证系统间通信的正常运行 在
  • mysql replication环境检查脚本

    author skate time 2013 05 13 mysql replication环境检查脚本 此脚本部署在slave端 可以通过短信或邮件监控slave的mysqld健康 replication环境健康 及复制延迟 脚本 mys
  • monorepo 下的 package tsc 构建

    很多个package都需要构建到每个项目的 lib 下 可以用 vscode 的 tasks json 任务去实现 具体 tasks json 的详情请看官网 https code visualstudio com docs editor
  • JavaScript中字符串的大小写转换(轮子,直接cv即可)

    此文件为js文件 封装模块按需导出即可 str 需要首字母转换的字符串 全部大写 export const all2Large str gt const arr str split let newStr 通过数组的forEach方法来遍历数
  • 解决Ubuntu下 anaconda 与ros opencv冲突的问题

    解决Ubuntu下 anaconda 与ros opencv冲突的问题 问题描述 解决办法之一 问题描述 在Ubuntu16 04上先后安装了Anaconda和ROS 然后在anaconda配置的pytorch环境中运行python代码 在
  • 【毕设】基于CycleGAN的风格迁移【一】环境搭建及运行代码

    源代码地址 CycleGAN源码 因为该篇内容包含Anaconda的环境管理及包的管理 可以选择参考 Anaconda安装 环境管理 包管理 实际演练例子 全网最详细 MrRoose1的博客 CSDN博客 一 搭配环境 1 首先把代码包下载
  • 递归、回溯-图的m着色问题

    1 问题描述 给定无向连通图G V E 和m种不同的颜色 用这些颜色为图G的各顶点着色 每个顶点着一种颜色 是否有一种着色法使G中每条边的2个顶点着不同颜色 这个问题是图的m可着色判定问题 输入 图的顶点的个数 颜色种类树m 输出顶点a与顶
  • C

    我们想定义一个全局变量 能够在多个文件中使用 举例说明比如说三个文件main c hello c hello h 想在main c和hello c中使用一个名字为a的变量 可能大家会简单地想直接在hello h里面定义一个变量unsigne
  • 网站渗透测试 越来越难渗透

    福利 网络安全重磅福利 入门 进阶全套282G学习资源包免费分享 最先 对于大家提出的难题 网站愈来愈难渗透 表明如今的安全防护技术性及其网站结构技术性的成熟情况是越来越健全了 次之 某一实际技术性方面的安全要求减少了 不可以整体表明渗透测
  • 分页组件的使用-jqPaginator

    工作中用到了分页 在github上面用到了一款分页组件 是叫jqPaginator 参考网站是 http jqpaginator keenwon com a3 上面可以下载 以及介绍怎么使用 贴出我使用的例子的代码 html div cla
  • 2020最新大厂高频微服务面试总结:Spring-Cloud+Spring-Boot+Dubbo(面试题+笔记+项目实战)

    话不多说 直接上题 SpringCloud面试题 什么是 Spring Cloud 使用 Spring Cloud 有什么优势 服务注册和发现是什么意思 Spring Cloud 如何实现 Spring Cloud 和dubbo区别 Spr
  • Linux MySQL 常见无法启动或启动异常的解决方案

    Linux MySQL 常见无法启动或启动异常的解决方案 在 Linux 上自建 MySQL 服务器 经常遇到各种无法启动或启动后异常的问题 本文列举一些常见问题的解决办法 注意 以下错误日志提示 都是查看 MySQL 错误日志得到 查看方
  • 深度理解volatile关键字

    Volatile java中可以把字段声明为volatile的 比如 public class AtomicInteger extends Number implements java io Serializable volatile变量