【javaEE面试题(五)在JMM(Java Memory Model (Java 内存模型))下谈volatile的作用】【保证内存可见 和 指令有序】

这篇具有很好参考价值的文章主要介绍了【javaEE面试题(五)在JMM(Java Memory Model (Java 内存模型))下谈volatile的作用】【保证内存可见 和 指令有序】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


【javaEE面试题(五)在JMM(Java Memory Model (Java 内存模型))下谈volatile的作用】【保证内存可见 和 指令有序】,面试题,JavaEE初阶,java,java-ee,开发语言

【javaEE面试题(五)在JMM(Java Memory Model (Java 内存模型))下谈volatile的作用】【保证内存可见 和 指令有序】,面试题,JavaEE初阶,java,java-ee,开发语言【javaEE面试题(五)在JMM(Java Memory Model (Java 内存模型))下谈volatile的作用】【保证内存可见 和 指令有序】,面试题,JavaEE初阶,java,java-ee,开发语言

volatile 能保证内存可见性
volatile 修饰的变量, 能够保证 “内存可见性”.
【javaEE面试题(五)在JMM(Java Memory Model (Java 内存模型))下谈volatile的作用】【保证内存可见 和 指令有序】,面试题,JavaEE初阶,java,java-ee,开发语言

代码在写入 volatile 修饰的变量的时候

  • 改变线程工作内存中volatile变量副本的值
  • 将改变后的副本的值从工作内存刷新到主内存

代码在读取 volatile 修饰的变量的时候

  • 从主内存中读取volatile变量的最新值到线程的工作内存中
  • 从工作内存中读取volatile变量的副本
    前面我们讨论内存可见性时说了, 直接访问工作内存(实际是 CPU 的寄存器或者 CPU 的缓存), 速度非常快, 但是可能出现数据不一致的情况.
    加上 volatile , 强制读写内存. 速度是慢了, 但是数据变的更准确了.

代码示例

在这个代码中

  • 创建两个线程 t1 和 t2
  • t1 中包含一个循环, 这个循环以 flag == 0 为循环条件.
  • t2 中从键盘读入一个整数, 并把这个整数赋值给 flag.
  • 预期当用户输入非 0 的值的时候, t1 线程结束.
import java.util.Scanner;

public class ThreadVolatile {
    static class Counter {
        public int flag = 0;
    }
        public static void main(String[] args) {
            Counter counter = new Counter();
            Thread t1 = new Thread(() -> {
                while (counter.flag == 0) {
                    // do nothing
                }
                System.out.println("循环结束!");
            });
            Thread t2 = new Thread(() -> {
                Scanner scanner = new Scanner(System.in);
                System.out.println("输入一个整数:");
                counter.flag = scanner.nextInt();
            });
            t1.start();
            t2.start();
        }
}

// 执行效果
// 当用户输入 非0值 时, t1 线程循环不会结束. (这显然是一个 bug)
  • t1 读的是自己工作内存中的内容.
  • 当 t2 对 flag 变量进行修改, 此时 t1 感知不到 flag 的变化

如果给 flag 加上 volatile

static class Counter {
    public volatile int flag = 0; 
}
// 执行效果
// 当用户输入非0值时, t1 线程循环能够立即结束.

volatile 不保证原子性

volatile 和 synchronized 有着本质的区别. synchronized 能够保证原子性, volatile 保证的是内存可见性.

代码示例
这个是最初的演示线程安全的代码

  • 给 increase 方法去掉 synchronized
  • 给 count 加上 volatile 关键字.
static class Counter {
    volatile public int count = 0;
    void increase() {
        count++;
   }
}
public static void main(String[] args) throws InterruptedException {
    final Counter counter = new Counter();
    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 50000; i++) {
            counter.increase();
       }
   });
    Thread t2 = new Thread(() -> {
        for (int i = 0; i < 50000; i++) {
            counter.increase();
       }
   });
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println(counter.count);
}

此时可以看到, 最终 count 的值仍然无法保证是 100000.

JMM下volatile作用

正常程序执行的过程中,会把主内存的数据,先加载到工作内存中,再进行计算处理.编译器优化可能会导致不是每次都真的读取主内存,而是直接取工作内存中的缓存数据.(就可能导致内存可见性问题)
volatile 起到的效果,就是保证每次读取内存都是真的从主内存重新读取文章来源地址https://www.toymoban.com/news/detail-562190.html

到了这里,关于【javaEE面试题(五)在JMM(Java Memory Model (Java 内存模型))下谈volatile的作用】【保证内存可见 和 指令有序】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • [JVM] 浅谈JMM(Java 内存模型)

    Java 内存模型(Java Memory Model,JMM)是 Java 虚拟机规范中定义的一种抽象计算机内存模型,用于描述 Java 程序在多线程下的内存访问行为。JMM 定义了线程之间共享变量的可见性和有序性规则,为开发者提供了一种可靠的同步机制,以避免并发程序中常见的线程安全问题。 JMM

    2024年01月16日
    浏览(15)
  • Java内存区域(运行时数据区域)和内存模型(JMM)

    Java内存区域(运行时数据区域)和内存模型(JMM)

    Java 内存区域和内存模型是不一样的东西,内存区域是指 Jvm 运行时将数据分区域存储,强调对内存空间的划分。 而内存模型(Java Memory Model,简称 JMM )是定义了线程和主内存之间的抽象关系,即 JMM 定义了 JVM 在计算机内存(RAM)中的工作方式,如果我们要想深入了解Java并发

    2024年02月12日
    浏览(16)
  • Java 内存模型(JMM)探寻原理,深度讲解

    Java 内存模型(JMM)探寻原理,深度讲解

    目录 一. 前言 二. 为什么会有内存模型 2.1. 硬件内存架构 2.2. 缓存一致性问题 2.3. 处理器优化和指令重排序 三. 并发编程的问题 四. Java 内存模型(JMM) 4.1. Java 运行时内存区域与硬件内存的关系 4.2. Java 线程与主内存的关系 4.3. 线程间通信 五. 主内存和工作内存 六. J

    2024年04月22日
    浏览(11)
  • Java内存模型(JMM)和volatile原理

    Java内存模型(JMM)和volatile原理

    目录 一、Java 内存模型 二、可见性 三、有序性 四、volatile原理  1、可见性保证 2、有序性保证 五、线程安全的单例 JMM即Java Memory Model,他定义了 主存(共享的数据) 、 工作内存(私有的数据) 抽象概念,底层对应着CPU寄存器、缓存、硬件内存、CPU指令优化等 JMM体现以下

    2024年02月09日
    浏览(8)
  • 【Java多线程学习7】JMM(Java内存模型)学习

    【Java多线程学习7】JMM(Java内存模型)学习

    JMM(Java内存模型),可以看作是 Java定义的并发编程相关的一组规范 ,除了抽象了 线程和主内存 之间的关系之外,其还规定了从 Java源代码 到 CPU可执行指令 的这个转化过程中要遵守哪些并发相关的原则和规范,其主要目的是 简化多线程编程 , 增强程序的可移植性 。 至于

    2024年02月11日
    浏览(14)
  • 区分什么是Java内存模型(JMM)和 JVM运行时数据区

    区分什么是Java内存模型(JMM)和 JVM运行时数据区

    Java的内存区域和内存模型是不一样的东西,内存区域是指 JVM 运行时将数据分区域存储,强调对内存空间的划分 。 而内存模型(Java Memory Model,简称 JMM )是 定义了线程和主内存之间的抽象关系,即 JMM 定义了 JVM 在计算机内存(RAM)中的工作方式 ,如果我们要想深入了解Java并

    2024年02月11日
    浏览(12)
  • 并发编程之三大特性及JMM内存模型

    并发编程之三大特性及JMM内存模型

    目录 原子性 如何保证原子性 可见性 如何保证可见性 有序性 如何保证有序性 Java内存模型(JMM内存模型) Java内存模型的一些关键概念: 主内存与工作内存交互协议 Java内存模型通过以下手段来确保多线程程序的正确性: 锁机制 volatile volatile禁止指令重排序  Happens-Before 并发三

    2024年01月19日
    浏览(13)
  • 【JUC系列-01】深入理解JMM内存模型的底层实现原理

    【JUC系列-01】深入理解JMM内存模型的底层实现原理

    JUC系列整体栏目 内容 链接地址 【一】深入理解JMM内存模型的底层实现原理 https://zhenghuisheng.blog.csdn.net/article/details/132400429 【二】深入理解CAS底层原理和基本使用 https://blog.csdn.net/zhenghuishengq/article/details/132478786 【三】熟练掌握Atomic原子系列基本使用 https://blog.csdn.net/zhenghuis

    2024年02月12日
    浏览(11)
  • CUDA编程模型系列六(利用shared memory和统一内存优化矩阵乘)

    CUDA编程模型系列六(利用shared memory和统一内存优化矩阵乘) 本系列教程将介绍具体的CUDA编程代码的细节 CUDA编程模型系列六(利用shared memory和统一内存优化矩阵乘)

    2024年02月11日
    浏览(11)
  • jmap(Memory Map for Java)Java内存映像工具

    jmap(Memory Map for Java)Java内存映像工具

    jmap(Memory Map for Java)命令用于生成堆转储快照(一般称为 heapdump 或 dump文件 ) 如果不使用jmap命令,要想获取Java堆转储快照也还有一些比较“暴力”的手段: 譬如 -XX:+HeapDumpOnOutOfMemoryError 参数,可以让虚拟机在内存溢出异常出现之后自动生成堆转储快照文件, 通过 -XX:

    2024年02月12日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包