JAVA内存模式-4-volatile

Java基础:volatile详解 Java基础:volatile1、volatile保证可见性1.1、JMM模型的引入1.2、volatile保证可见性的代码验证1.2.1、无可见性代码验证1.2.1、volatile保证可见性验证2、volatile不保证原子性 问:请谈谈你对volatile的理解? 答:volatile是Java虚拟机提供的轻量级的同步机制,它有3个特性: 1)保证可见性 2)不保证原子性 3)禁止指令重排 刚学完java基础,如果有人问你什么是volatile?它有什么作用的话,相信一定非常懵逼… 可能看了答案,也完 阅读详情

volatile特性

可见性:对一个volatile变量的读,总是能看到任意线程对这个volatile变量最后的写入。

原子性:对任意单个volatile变量的读写具有原子性,但类似于volatile++这种复合操作不具有原子性。

从happens-before角度来看volatile的读写

从可见性来看,volatile的写-读,与锁的释放-获取具有相同的内存效果:volatile写和锁释放、volatile读与锁获取具有相同的内存效果。

class volatileTest{

int a = 0;

volatile boolean flag = false;

public void init(){

a = 1;//操作1

flag = true;//操作2

}

public void print(){

if(flag){

int j = a;//操作3

System.out.println(j++);//操作4

}

}

}

从happens-before来看:

  1. 程序顺序规则:1 happens-before 2,3 happens-before 4。
  2. volatile变量规则:2 happens-before 3。
  3. 传递性:1 happens-before 4。

黑色箭头表示程序顺序规则;

橙色箭头表示volatile规则;

蓝色箭头表示组合这些规则后提供的happens-before保证。

volatile读写的内存过程

volatile写的时候,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存。

volatile读的时候,JMM会把该线程对应的本地内存置为无效后,线程接下来再从主内存中读取共享变量。

如何实现volatile小村效果?

因为JAVA、CPU会对代码、字节码执行重排序,因此这里就从编译器重排序、处理器重排序来分析。为了实现volatile内存效果,JMM会分别限制这2种类型的重排序类型。

JMM针对编译器制定的volatile重排序规则:

是否能重排序

第二个操作

第一个操作

普通读写

Volatile读

Volatile写

普通读写

 

 

NO

Volatile读

NO

NO

NO

Volatile写

 

NO

NO

从上表看出:

  1. 当第二个操作是volatile写时,不管第一个操作是什么,都不能重排序从而确保volatile写之前的操作不会被编译器排序到volatile写之后。
  2. 当第一个操作是volatile读时,不管第二个操作是什么,这个规则确保volatile读之后的操作不会被编译器重排序到volatile读之前。
  3. 当第一个操作是volatile写,第二个操作是volatile读时,不能重排序。

JMM针对CPU重排序制定的volatile重排序规则:

编译器在生成字节码文件时会在指令序列中插入内存屏障。但对于编译器而言如何插入最少的内存屏障指令呢?对不起,无法确定,只能是本着“宁可错杀一千不可放过一个”来插入内存屏障指令:(优化是服从于JSR-133规范的,首先确保JSR-133规范,然后再谈优化)

  1. 分别在每个volatile写操作的前面插入一个StoreStore屏障、后面插入一个StoreLoad屏障。
  2. 分别在每个volatile读操作的后面依次插入一个LoadLoad屏障、一个LoadStore屏障。

volatile写

volatile写前面的StoreStore屏障指令能前面所有普通读写的结果刷新到主内存,这样所有的CPU中缓存的数据均一致。

volatile写后面的StoreLoad屏障指令则非常有趣,为什么是StoreLoad呢?因为考虑到volatile写后面可能与volatile读/写操作做重排序,或者,volatile写后面直接就是return的话(return之后就没有操作了必须对其他CPU可见,如果不是return的话,你也得必须对其他CPU可见),为了能及时刷新到主内存来确保所有CPU可见,JMM这里采用保守策略:在每个volatile写的后面、每个volatile读的前面插入一个StoreLoad屏障来达成volatile写的内存效果。

另外还可以从一个常见场景来做解释:JMM选择在每个volatile写的后面插入一个StoreLoad屏障指令,是因为常常是一个写线程写volatile变量,N个读线程读同一个volatile变量,当N 大大超过写线程时(此时写线程就1个而已),通过在volatile写后面的StoreLoad来确保写的结果及时刷新到主内存进而提高执行效率。

volatile读

LoadLoad屏障指令确保禁止CPU把volatile读与下面的普通读做重排序。

LoadStore屏障指令确保禁止CPU把volatile读与下面的普通写做重排序。

(我觉得,这里可以总结出一句话:为了实现volatile读写的内存可见性,写必须确保其准备工作的可见性以及结果的可见性,读必须确保其优先性)

volatile发展历史

int a = 0;

volatile boolean flag = false;

public void writer(){

a = 1;

flag = true;

}

public void reader(){

if(flag){

int i = a;

......

}

}

JSR-133旧内存模型中,不允许volatile变量之间重排序但允许volatile变量与普通变量重排序,对于上述代码中可能存在如下情况:

Writer方法中a和flag不存在数据依赖性,因此,重排序可能出现的情况是:flag=true;a=1;

那么假如A线程执行writer方法,B线程执行reader方法,那么显而易见,结果不是我们想要的结果。

为了避免这个问题发生,JSR-133在新内存模型中对volatile进行了强化:

严格限制JMM和CPU对volatile变量与普通变量的重排序,确保volatile的写-读和锁的释放-获取具有相同的内存语义。

 

 

 

 

80MHz~100MHz频谱分析仪设计 由理论分析可知,经过乘法器后输出的信号为频率为w1+w2的高频信号和w1-w2的低频信号,除了想要采样的直流信号外,最小的信号频率为100kHz。因此,经过一系列推导可以得到该滤波器的元件C1,C2,C3,R1,R2的近似值分别为:C1=2.36nF,C2=32.1nF,C3=1.07nF,R1=1.39k,R2=2.84k。AK,此时的频率w2即为被测信号的频率,待测信号源电压幅度为,因此为了能达到直流采样的设计,我们将本振源的频率输出范围做成80~110 MHz,提高了题目的频率要求。 阅读详情

相关推荐

iPhone存储空间耗尽自救指南:从“白苹果”死锁到成功保数据刷机

本文详细介绍了iPhone存储空间耗尽导致'白苹果'死锁的解决方案,通过保留数据刷机方法成功恢复设备运行。文章分享了从失败尝试到最终成功的完整流程,包括关键操作步骤和预防措施,帮助用户在紧急情况下保住重要数据。

weixin_32578161的博客 290

Java并发编程图册学习(六) 面试 volatile 关键字

对一个 volatile 域的写, happens-before 于任意后续对这个 volatile 域的读 一、happens-before 之 volatile 变量规则 JMM 针对编译器定制的 volatile 重排序的规则,那 JMM 是怎样禁止重排序的呢? 答案是内存屏障 二、内存屏障 (Memory Barriers / Fences) 为了实现 volatile 的内存语义,编译器在生成字节码时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序 这句话有点抽象,..

panjianlongWUHAN的专栏 355

专项1.CCS代码补全与快捷键优化全攻略

本文全面解析CCS开发环境的代码补全功能与快捷键优化技巧,包括内容辅助触发机制、快捷键自定义配置、编码效率提升方法等实用内容。通过详细步骤指导开发者优化CCS配置,实现高效的代码自动补全和个性化快捷键设置,显著提升嵌入式开发效率。

kotlin6android的博客 223

Happens-Before 规则总结

在并发编程中Happens-Before 规则是相当重要的规则,它所代表的意思是前面一个操作对后续操作是可见的,共有6项规则如下: 程序的顺序性规则 volatile 变量规则 传递性 管程中锁的规则 线程 start() 规则 线程 join() 规则 分别对以上6种规则进行解释: 1.程序的顺序性规则 程序的顺序性指的是代码会按照书写的顺序去执行,也就是单线程方式。 2.volatile 变量规则 对一个 volatile 变量的写操作, Happens-Before 于后续对这个 volatile的读

Talk is cheap 304

802.1AS时间同步机制深度解析:从Sync报文到多域冗余设计

本文深度解析了802.1AS时间同步机制,从Sync与Follow_Up报文的核心交互原理入手,详细阐述了其如何通过精确的时钟频率比测量、链路延迟计算和驻留时间补偿来实现微秒乃至纳秒级同步。文章进一步探讨了802.1AS-2020版本引入的多时钟域冗余设计,为构建高可靠的车载TSN网络提供了关键见解和实战配置指南。

pytorch8learner的博客 460

游戏大厂技术护城河——为什么你抄不了原神?

│ │ │ │ ↓ 通过 │ │ │ │。│ │ │ │ ↓ 成功 │ │ │ │。│ │ │ │ ↓ 完成 │ │ │ │。│ │ │ │ ↓ 达标 │ │ │ │。

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 71

测试volatile变量的读写性能

volatile变量与非volatile变量的区别在于,volatile变量每次读都需要去主内存读取最新的值,每次写也需要写回到主内存;非volatile变量允许在缓存中读写以加快计算速度。

@甘道夫@的专栏 3677

行为预测模型:Social LSTM与Graph Neural Networks

行为预测模型:Social LSTM与Graph Neural Networks ,人工智能,计算机视觉,大模型,AI,本文围绕行为预测模型Social LSTM与Graph Neural Networks展开,介绍了两者的基础概念、原理、应用场景,还对比了它们在优势、劣势和适用场景上的不同,最后给出了相应的代码示例。Social LSTM基于LSTM,通过社交池化层处理多智能体交互;图神经网络处理图结构数据,靠消息传递获取信息,二者各有侧重,适用于不同场景。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 15万+

Java高并发编程---volatile关键字

volatile的特性 可见性:对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。 原子性:对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性。   volatile写-读建立happens-before关系  从JDK5开始,volatile变量的写-读可以实现线程之间的通信。从内存语义的角...

喜三仔的世界 432

【SAP HANA 46】关于HANA CPU高峰到 80-100%

关于HANA CPU高峰到 80-100%

探索 Java 编程的技巧、最佳实践和解决方案。本博客提供针对 Java 开发者的实用指南,涵盖从基础到高级话题,旨在提升编程效率和技能。 429

轴承故障诊断领域的论文到底有多水

这个是最让人困惑的,就好像你说自己证明了某个方法更好,但是你却没有交代自己怎么做的,或者说你交代的过程有外行话或者逻辑上的缺陷,但是你就这么给出个结果完事了。由于自己没有足够大的学术交流圈子,为了尽量避免误判,我在原来13篇论文的基础上又读了18篇,这些论文至少都出自中文核心,有一些还有EI的title,事实上近几年能找到的文章也不算多,这些基本能说明问题了。当然,还有更多细节,比如说损失函数你得交代吧,模型超参数得介绍全吧,至少数据集是哪个工况下的得说吧,当你想复现这些论文,关注点在这些地方的时候。

weixin_50642818的博客 3052

volatile特性详解

volatile变量对所有线程是立即可见的 包含两个意思: 对一个volatile变量的读总是能看到任意线程对这个变量最后的写,即每次读取volatile变量的时候,会使线程工作内存中的变量副本无效,从而必须从主内存中更新变量值。 对一个volatile变量进行写操作后,会立刻将修改的值同步到主内存,以便于后面读取该变量的线程获取到的是最新的值。 这里volatile的特性可能一眼就能够看清...

奋进的小白粥 2441

甲基化生物信息学分析及批次效应校正全流程

本文系统阐述了DNA甲基化数据分析中的批次效应问题及解决方案。甲基化数据(β值和M值)对实验批次差异高度敏感,可能导致假阳性结果。文章详细介绍了批次效应检测方法(PCA可视化、BEclear定量评分)和校正流程,包括数据预处理、参数化(ComBat-met)与非参数化(BEclear)校正方法,并提供了完整的R代码实现。重点解决了β值有界分布与统计模型假设冲突的问题,为甲基化研究的可靠性提供技术保障。

huanghm88的专栏 109

4、Java内存模型、volatile原理、CPU缓存结构、balking模式、单例模式

本章内容 上一章讲解的Monitor主要关注的是访问共享变量时,保证临界区代码的原子性 这一张进一步深入学习共享变量在多线程之间的【可见性】问题与多条指令执行时的【有序性】问题 1、Java内存模型 JMM即Java Menory Model,它定义了主存,工作内存的抽象概念,底层对应着CPU寄存器、缓存、硬件内存、CPU指令优化等。 JMM 体现在以下几个方面 原子性 - 保证指令不会受到线程上下文切换的影响 可进行 - 保证指令不会受到CPU缓存的影响 有序性 - 保证指令不会受到CPU指令优化的影响

u011569827的博客 334

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

锁的内存语义

一、锁的释放和获取的内存语义 当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中。 当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被监视器保护的临界区代码必须要从主内存中去读取共享变量。 对比锁释放-获取的内存语义与volatile写-读的内存语义: 可以看出:锁释放与volatile写有相同的内存语义;锁获取与vola...

LinDongTian 214

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

MiniCPM-o-4.5-nvidia-FlagOS代码解释能力展示:理解复杂Java八股文示例

本文介绍了如何在星图GPU平台上自动化部署MiniCPM-o-4.5-nvidia-FlagOS镜像,并展示了其强大的代码理解与分析能力。该镜像能够深入解读复杂的Java代码,例如剖析单例模式中的双重检查锁定机制,为开发者提供代码设计思路、潜在风险及优化建议,有效辅助代码评审与学习。

weixin_34535286的博客 77

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Java 之 volatile 详解

volatile 可以看做是轻量级的 synchronized,它只保证了共享变量的可见性,是Java虚拟机提供的轻量级的同步机制。在线程 A 修改被 volatile 修饰的共享变量之后,线程 B 能够读取到正确的值。Java 在多线程中操作共享变量的过程中,会存在指令重排序与共享变量工作内存缓存的问题。volatile 一共有三大特性,保证可见性不保证原子性禁止指令重排。

流华追梦的专栏 8520

volatile原理(内存屏障)

volatile 场景 一个线程写,其他线程读的情况 double-check-lock时,synchronized同步代码块外共享变量的指令重排序问题 同步机制 volatile 是 Java 虚拟机提供的轻量级的同步机制(三大特性) 保证可见性 不保证原子性 保证有序性(禁止指令重排) 性能:volatile 修饰的变量进行读操作与普通变量几乎没什么差别,但是写操作相对慢一些,因为需要在本地代码中插入很多内存屏障来保证指令不会发生乱序执行,但是开

2301_79437276的博客 2330

Java:java学习笔记之volatile关键字的简单理解和使用

volatile关键字的简单理解和使用volatile关键字1、定义2、并发编程的3个基本概念2.1、原子性2.2、可见性2.2.1、Java的内存模型JMM以及共享变量的可见性2.2.1.1、举例说明2.2.2、可见性2.3、有序性3、锁的互斥和可见性4、volatile变量的特性4.1、保证可见性4.2、保证有序性4.2.1、指令重排4.2.1.1、happens-before原则4.2.1.2、解决方法:volatile关键字4.3、不保证原子性5、volatile原理6、volatile的使用6.1

JMW1407的博客 1万+

Java内存模式以及volatile关键字的使用

Java内存模式以及volatile关键字的使用

y516369的博客 462

Java 并发:volatile 内存可见性和指令重排

1. 正确认识 volatile volatile变量具有synchronized的可见性特性,但是不具备原子特性。volatile变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。因此,单独使用volatile还不足以实现计数器、互斥锁或任何具有与多个变量相关的不变式(Invariants)的类(例如 “start <=end...

钱立清的博客 3043

volatile使用和Java单例模式中的volatile理解

为了更好理解单例模式中的volatile之前,需要先简单了解下Java的内存模型。 Java的内存模型 Java内存模型简称JMM(Java Memory Model),是Java虚拟机所定义的一种抽象规范,用来屏蔽不同硬件和操作系统的内存访问差异,让java程序在各种平台下都能达到一致的内存访问效果。 Java内存模型是什么样子的呢?可以理解为下图的样子: 解释下: 1、主内存(Main M...

魔教中人 435

Java中的volatile关键字详解

volatile关键字提供了一种比synchronized更轻量级的线程安全机制,但它只能保证可见性和有序性,不能保证原子性。正确使用volatile可以避免不必要的同步开销,但在需要保证复合操作原子性或互斥性的场景下,仍然需要使用synchronized或其他并发工具。理解volatile的关键在于理解Java内存模型(JMM)以及happens-before原则,它在多线程编程中是一个非常有用的工具,但需要谨慎使用。

weixin_43680337的博客 1400

Java DCL 单例模式真的需要对变量加 Volatile 吗?

原文链接:https://zhuanlan.zhihu.com/p/385271959 目录代码展示DCL分析DCL单例变量加volatile关键字的原因Java对象创建过程volatile修饰单例变量的原因不同角度下的对象创建原理从C++角度分析对象创建从Java角度分析对象创建小结CPU模型与DCL完整的Java DCL实例 代码展示 对于单例模式来说,我们为了保证一个类的实例在运行时只有一个,所以我们首先将构造器私有化,禁止在其他地方创建该类的对象,同时我们将单例对象保存在该类的静态变量中,当我们需要

寒泉 5万+

JUC学习:volatile与内存屏障

volatile的概念与读写流程,内存屏障的概念与作用,以及volatile如何实现了其可见性与有序性。

qq_45266399的博客 2395

JAVA volatile修饰符的作用

volatile修饰符的作用前言线程可见性简绍JAVA线程模型案例指令重排简绍案例 前言 volatile在多线程开发中是可以经常看到的变量修饰符,本文主要是比较浅显的介绍volatile的作用。 线程可见性 简绍 JAVA线程模型 案例 指令重排 简绍 案例 参考: https://www.cnblogs.com/dolphin0520/p/3920373.html ...

hellopeng1的博客 1489
上一篇: JAVA内存模式-3-顺序一致性
下一篇: JAVA内存模式-5-锁
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值