volatile与java内存模型的那点关系

西门子840D新建项目 1、需要一个32位的WIN7或者XP系统,并且已经在系统中安装完成西门子840Dsl开发包和VS2008。(我采用的是XP系统虚拟机) 2、在开始->所有程序找到如下位置 3、在这个位置打开Visual Studio 4、文件->新建->项目 名称和位置都可以随意更改,点击确定。 5、在左侧选择第二个选项进入下面的界面 点击“Add Screen”按钮 可以修改“class name”然后点击“OK”返回上一个界面,再点击“Add Form” 可以修... 阅读详情

有一半(1/3+1/6)的关系!

因为java内存模型的三个特性,volatile满足了两个!

1、可见性(满足)

2、有序性(满足了一半)

3、原子性(不满足)

下面解释下:

可见性:多个线程使用到同一个变量时,一旦有一个线程修改了变量,其他线程再读取时一定是读取到这个修改后的值。

有序性:程序执行的顺序按照代码的先后顺序执行。不会发生指令重排序,或者指令重排序在多线程环境下显现出有序性!

原子性:一个不可以再分割的操作即为原子操作。如:a = 0(a为int类型);

 

关于有序性(满足了一半),我下面举两个例子说明一下!

演示下指令重排序的例子1:(a加了volatile修饰,依然会发生指令重排序的!!)

public class Test {
    private volatile int a;
    private int b;


    public static void main(String[] args) {
        for (int i = 0; i < 10000; i++) {
            final Test test = new Test();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    test.a = 1;
                    test.b = 1;//发生指令重排序的话,b会被先赋值,a还是默认值0
                }
            }).start();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    if (0 == test.a && test.b == 1) {
                        System.out.println("发生指令重排序!");
                    }
                }
            }).start();
        }
    }
}

运行了几次,控制台打印出了:

发生指令重排序!

 

下面再举例一个volatile“禁止”了指令重排序的例子2:(指令重排序会有内存屏障)

参考自:https://blog.youkuaiyun.com/weixin_37817685/article/details/80261549

public class Singleton {
        private Singleton() { }
        private volatile static Singleton instance;
        public Singleton getInstance(){
            if(instance==null){
                synchronized (Singleton.class){
                    if(instance==null){
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
}

注意:singleton = new Singleton(),这不是一个原子操作,一共有3个步骤:

1. 给 singleton 分配内存
2. 调用 Singleton 的构造函数来初始化成员变量,形成实例
3. 将singleton对象指向分配的内存空间(执行完这步 singleton才是非 null了)

假如没有volatile修饰,有两个线程同时调用了getInstance()方法,其中一个线程A执行到singleton = new Singleton();这一句,发生了指令重排序【1-3-2】,当2还没有执行的时候,线程B发现instance不为null,直接返回instance(此时instance还没有成员变量的信息,因为2还没有执行),线程B使用instance就可能会出错了。

volatile关键字的一个作用是“禁止”指令重排,把instance声明为volatile之后,对它的写操作就会有一个内存屏障,这样,在它的赋值完成之前,就不用会调用读操作。

注意:volatile阻止的不是singleton = new Singleton()这句话内部【1-2-3】的指令重排,而是保证了在一个写操作【1-2-3】或者【1-3-2】完成之前,不会调用读操作(if (instance == null))。

从例子2可以看出,我必须等到你写完了才能读(volatile的写屏障),表现出来的指令重排序在多线程环境下显现出有序性。

 

下面说一下volatile满足了可见性却不满足原子性的问题!代码如下:

    private volatile static int count = 0;

    public static void main(String[] args){
        for (int i = 0; i < 10000; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    count++;
                    System.out.println("count=" + count);
                }
            }).start();
        }
    }

 有时打印到9999,有时打印到9998。是不是发现不对劲了,看看上面的可见性:

可见性:多个线程使用到同一个变量时,一旦有一个线程修改了变量,其他线程再读取时一定是读取到这个修改后的值。

其实是因为count++(count = count + 1)并非是一个原子操作,看下图:

图片来源:https://blog.youkuaiyun.com/strivenoend/article/details/80440884

 

例如当主存中count变量为99,现在线程A去Read主存中的count,并存到线程内部工作栈99,然后执行count+1了,这时,另一个线程已经将主存中的count更新为100了,这会使得线程内部工作栈count为99的副本失效(使缓存行无效)。但是线程A并不需要去读取主存中的count(100),而是将自己运算的count+1(100)写到线程的缓存行,然后再写回主存,还是100!!!两个线程都count++了,结果count才加了1。

出现上述问题的原因是,count++不是一个原子操作,volatile不满足原子性。

 

如果对您有用的话赞一下呗!谢谢!

 

STM32 HAL SDADC DMA 由于项目需要使用STM32F373单片机的SDADC功能对电位计进行检测,网上资料比较少,踩了很多坑,下面进行总结。 阅读详情

相关推荐

单细胞分析(19)—— 单细胞转录组基因集评分方法

在单细胞RNA测序(scRNA-seq)分析中,基因集评分(Gene Set Scoring)是一项关键任务,能帮助研究者识别细胞功能状态

阅读文献,记录学习笔记 2439

volatile与Java内存模型

内存屏障:是一种 屏障指令,它使得 CPU或编译器 对屏障指令的前和后所发出的内存操作 执行一个排序的约束。也叫内存栅栏 或栅栏指令。volatile写之前的操作,都禁止重排序到volatile之后volatile读之后的操作,都禁止重排序到volatile之前volatile写之后volatile读,禁止重排序的。

309

用STM32F103单片机控制电调制动无刷电机

用电调控制无刷电机制作遥控飞艇 蓝牙控制 调控电调 无刷电机 用电调控制无刷电机制作遥控飞艇 代码区 mian.c #include "delay.h" #include "sys.h" #include "usart.h" #include "usart3.h" #include "timer.h" #include "led.h" #include "key.h" int main(v...

子非鱼 的博客 2万+

一文读懂Java内存模型(JMM)及volatile关键字

点赞再看,养成习惯,公众号搜一搜【一角钱技术】关注更多原创技术文章。 本文 GitHub org_hejianhui/JavaStudy 已收录,有我的系列文章。 前言 并发编程从操作系统底层工作的整体认识开始 上一篇我们从操作系统底层工作的整体了解了并发编程在硬件以及操作系统层面的一些知识,本篇我们继续来学习JMM模型以及Volatile关键字的那些面试必问的一些知识点。 什么是JMM模型? Java 内存模型(Java Memory Model 简称JMM)是一种抽象的概念,并不真实存在,它描..

org_hjh的博客 856

STM32+Air724UG基于阿里云物联网平台的OTA远程升级实战指南

本文提供了一套基于STM32微控制器与Air724UG 4G Cat.1通信模组,通过阿里云物联网平台实现OTA远程升级的完整实战指南。文章详细阐述了BootLoader与用户程序的分工、云端配置、固件下载与烧写流程,并分享了关键代码实现与常见问题排查方法,帮助开发者快速为物联网设备部署稳定可靠的无线升级功能。

weixin_28285943的博客 514

【STM32】BLDC驱动&控制开发笔记 | 07_SPI通信测试 - STM32F407用SPI配置DRV8323驱动芯片

使用STM32F407的SPI通信功能配置DRV8323S驱动芯片的详细过程说明。

这里是 F菌的进阶之路。 6289

Java内存模型(JMM)与volatile详解

JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(栈空间),用于存储线程私有的数据,而Java内存模型中规定。

老男孩的架构路 360

压电传感器信号放大难题?用运放设计电荷放大器的5个关键步骤

本文详细解析了压电传感器信号放大难题,并提供了用运放设计电荷放大器的5个关键步骤。从电压放大到电荷放大的范式转换,到运放选型、反馈网络设计、PCB布局及频响特性验证,帮助工程师解决工业自动化中的信号衰减问题,提升测量精度和稳定性。

weixin_27303545的博客 447

深入理解Java内存模型(四)——volatile

volatile 的特性 当我们声明共享变量为 volatile 后,对这个变量的读 / 写将会很特别。理解 volatile 特性的一个好方法是:把对 volatile 变量的单个读 / 写,看成是使用同一个监视器锁对这些单个读 / 写操作做了同步。下面我们通过具体的示例来说明,请看下面的示例代码: class VolatileFeaturesExample { volatile ...

怀素的专栏 707

基于STM32的最简易蓝牙遥控小车

基于STM32的蓝牙遥控小车,基于HAL库编写代码,具有移动功能,读者可自行添加其他扩展功能。按下状态的对应关系:2前进,4左转,5停止,6右转,8后退,松开状态都是5,都选择16进制。首先按照小车的图纸把小车的机械部分装好。做这个小车的成本在200元左右,包括焊接设备,杜邦线等。

weixin_43469377的博客 1万+

不只是CPU主频:深入解析英飞凌Aurix TC3xx各外设时钟树(CAN、以太网、Flash时序如何配置)

本文深入解析英飞凌Aurix TC3xx系列微控制器的外设时钟树配置,涵盖CAN、以太网和Flash时序的优化方法。通过详细分析时钟系统架构、关键外设配置及多外设协同设计策略,帮助工程师实现高性能汽车电子控制单元(ECU)开发。特别关注系统时钟的灵活配置与EMC优化技巧,提升系统实时性和可靠性。

weixin_29189373的博客 400

Java内存模型与volatile关键字不为人知的关系

1 博文主旨 行文主要围绕以下3个问题展开阐述: volatile关键字作用有哪些? volatile关键字有哪些运用场景? Java内存模型与volatile之间究竟有何关联? 2 Java内存模型 VS JVM运行时数据区 2.1 Java内存模型 Java虚拟机支持多线程任务的执行。在多线程运行场景下,若线程间未能保证同步的正确性,线程的行为可能会出现混淆和违反直觉。 在这种情况下,我...

Blake的博客 295

Cadence元件库介绍

Cadence安装完之后,在安装目录下,会有默认自带的一些常用元件库。例如,我的Candece安装目录为: D:\Cadence\Cadence_SPB_17.2-2016 元件库所在目录为: D:\Cadence\Cadence_SPB_17.2-2016\tools\capture\library 各个元件库对应的内容如下: AMPLIFIER.OLB 共 182 个零件,存放模拟放大器 IC,如 CA3280,TL027C,EL4093 等。 ARITHMETIC.OLB 共 182 个零件,存放

年少时的棉花糖 1万+

Volatile详解,太详细了-JMM java内存模型

Volatile可能是面试里面必问的一个话题吧,对他的认知很多朋友也仅限于会用阶段,今天我们换个角度去看看。 先来跟着丙丙来看一段demo的代码: 你会发现,永远都不会输出有点东西这一段代码,按道理线程改了flag变量,主线程也能访问到的呀? 为会出现这个情况呢?那我们就需要聊一下另外一个东西了。 JMM(JavaMemoryModel) JMM:Java内存模型,是java虚拟机规范中所定义的一种内存模型,Java内存模型是标准化的,屏蔽掉了底层不同计算机的区别(注意这个跟JVM

没有伞的孩子必须努力奔跑!—小林 1万+

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

通俗易懂的Java内存模型与Volatile详解

文章目录一、Java 内存模型二、volatile详解 一、Java 内存模型     Java 内存模型试图屏蔽各种硬件和操作系统的内存访问差异,以实现让 Java 程序在各种平台下都能达到一致的内存访问效果。 (一)主内存与工作内存     处理器上的寄存器的读写的速度比内存快几个数量级,为了解决这种速度矛盾,在它们之间加入了高速缓存。     加入高速缓存带来了一个新的问题:缓存一

qq_46993700的博客 3124

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

全面理解Java内存模型(JMM)及volatile关键字

【版权申明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.youkuaiyun.com/javazejian/article/details/72772461 出自【zejian的博客】 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深...

zejian的博客 18万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Java内存模型:Java中的volatile有什么用?

好啦,今天这节课就结束啦,这节课我们学习了Java内存模型。从这节课中,我们了解到JSR 133中所描述的Java内存模型是一种理论模型,它的规则非常少,以至于连控制流依赖和数据流依赖都没有规定,这导致JSR133文档讨论了很多在现实中根本不存在的情况。而我们在讨论JMM的实现时,必然会与具体的CPU相联系。Doug Lea将JMM做了简单的翻译,使用软件程序员可以看懂的语言重新阐释了JSR 133文档。到这里,这节课开始处所讲的volatile的机制,其答案也就明晰了。

qq_33240556的博客 1041

Volatile之Java内存模型概念

本文主要讲解Java内存模型和并发的基础概念,目的是为下文“volatile实践”一文做铺垫。

三少爷的剑 1131

Java 内存模型之 volatile 详解

本文深入探讨了Java并发编程中volatile关键字的核心机制与应用场景。文章首先分析了并发编程的三大核心问题:可见性、原子性和有序性问题。然后详细解析了Java内存模型(JMM)的基础原理,包括主内存与工作内存的交互机制。重点阐述了volatile的语义特性,通过内存屏障实现可见性和禁止指令重排序,并对比了其与synchronized的差异。文章还介绍了volatile的典型应用场景(如状态标志、安全发布等)及其局限性,特别强调它不保证原子性操作。最后提供了最佳实践指导,包括何时使用/避免使用volat

油墨香^-^的博客 960

Java 内存模型 与 volatile原理

JMM 即 Java Memory Model,它定义了主存、工作内存抽象概念,底层对应着 CPU 寄存器、缓存、硬件内存、CPU 指令优化等。JMM 体现在以下几个方面。

xiongyuqing的博客 1090

深入理解 Java 内存模型与 volatile 关键字

Java 内存模型(Java Memory Model,JMM)是 Java 并发编程的核心基础,它定义了多线程环境下程序的执行规则。JMM 并非指代物理内存结构,而是 Java 虚拟机规范中定义的一组抽象规则和约束。可见性问题:在多核 CPU 环境下,由于每个 CPU 都有独立的缓存,一个线程对共享变量的修改可能不会立即被其他线程看到。原子性问题:某些操作需要多个步骤完成(如i++),在并发环境下可能会被其他线程打断。有序性问题。

Toroto5的博客 1408

Java内存模型(JMM)与Volatile关键字底层原理

Java内存模型(JMM)与Volatile关键字底层原理

安静的软件工程师 1076

jvm内存模型和java内存模型

初识java虚拟机,就碰到一系列不懂的问题。我们以前常说java把局部变量放在栈里,new出来的变量放在堆里,然后堆里的数据不定时就给回收了。然后,如果是多线程的话,每个线程自己都有会一个私有的虚拟机栈,运行每个方法时都会创建一个栈帧,栈帧里存储着局部变量啦等信息,方法结束栈帧就出栈。这好像就是我们对java内存模型的第一次理解吧。直至今天,我看了java线程通讯之java内存模型,出现了主内存、...

番茄炒土豆的博客 9445

java内存模型与volatile

很不错的文章,清晰、透彻。原文地址:http://jiangzhengjun.iteye.com/blog/652532 内存模型描述的是程序中各变量(实例域、静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存取出变量这样的低层细节。 每一个线程有一块工作内存区,其中保留了被所有线程共享的主内存中的变量的值的拷贝。为了存取一个共享的变量,一个线程通常先获取

肖扬的专栏 525

Java内存模型与volatile

Java内存模型(JMM)         在介绍volatile之前,先介绍一下java内存模型(JMM)。如下图所示:         每个Java线程在运行的过程中,都有一个与之对应的工作内存,这个内存空间是线程私有的。         当多个线程同时修改同一个对象时,线程会首先从主内存里面取出对象到工作内存当中去。然后更改完工作内存之后,再更新到主内存当中去。因此,对于普通的

Fouy_风度玉门。 452

Java中volatile详解

絮叨 这一篇也算是Java并发编程的开篇,看了很多资料,但是轮到自己去整理去总结的时候,发现还是要多看几遍资料才能完全理解。还有一个很重要的点就是,画图是加深印象和检验自己是否理解的一个非常好的方法。 一、Volatile怎么念? 看到这个单词一直不知道怎么发音 英 [ˈvɒlətaɪl] 美 [ˈvɑːlətl] adj. [化学] 挥发性的;不稳定的;爆炸性的;反复无常的 复制代码 那Java中volatile又是干啥的呢? 二、Java中volatile用来干啥...

Mick_^_^的博客 1683
上一篇: 轻松看懂synchronized和wait()、notify()、notifyAll()的关系
下一篇: 由.java和.c文件生成.so文件的艰苦路程
river66
博客等级 码龄8年 76粉丝 108原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值