【javaEE面试题(五)在JMM(Java Memory Model (Java 内存模型))下谈volatile的作用】

volatile的作用

        • JMM下volatile作用

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

volatile 能保证内存可见性
volatile 修饰的变量, 能够保证 “内存可见性”.
在这里插入图片描述

代码在写入 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 起到的效果,就是保证每次读取内存都是真的从主内存重新读取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/21046.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于低代码平台的项目设计的一般流程及低代码平台(基于iVX)与MVC的关系

基于低代码平台的项目设计的一般流程及低代码平台&#xff08;基于iVX&#xff09;与MVC的关系 1.基于低代码平台的项目设计的一般流程a.流程图b.MVC架构应用于iVX项目的各分层排序&#xff1a;&#xff08;1&#xff09;第一步&#xff1a;写M&#xff08;2&#xff09;第二步…

Linux+Docker+Gitlab+Jenkins+虚拟内存

最近想研究一下怎么自动化发布项目,于是找到了gitlab+jenkins这个组合,正好借机也研究一下最近很火的docker技术。本篇共分为五部分,分别为安装要求,内存虚拟化,安装docker,安装gitlab,安装jenkins。 一、 安装要求 1 Docker安装要求: 1.1 操作系统 Docker只支持64…

数据科学竞赛之吃鸡排名预测答辩PPT

该课程我的成绩为优秀&#xff0c;PPT格式仅供参考。

Jquery

一、概念 JQuery是一套兼容多浏览器的JS脚本库&#xff0c;核心理念是写的更少&#xff0c;做的更多&#xff0c;使用Jquery将极大的提高编写JS代码的效率。 下载与安装&#xff1a;下载&#xff1a;只需要在官网下载js文件&#xff0c;也可以用在线的。 安装&#xff1a;在需要…

echarts折线图横向渐变填充

这种情况&#xff0c;需要后端去计算&#xff0c;如何把不同分段的值赋予不同的颜色&#xff0c;然后组合成下面我们需要的格式就可以实现 drawLine1() {if (document.getElementById(s1) ! null) {var that thislet heightNum (this.porosityList.maxDepth-this.porosityLis…

基于javascript的可以自定义设置圆几等份的抽奖示例

基于javascript的可以自定义设置圆几等份的抽奖示例 效果示例图代码示例使用class 效果示例图 代码示例 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style type"text/css">* {padding…

60题学会动态规划系列:动态规划算法第五讲

子数组系列题目 文章目录 1.最大子数组和2.环形子数组的最大和3.乘积最大数组4.乘积为正数的最长子数组长度5.等差数列划分6.最长湍流子数组7.单词拆分8.环绕字符串中唯一的子字符串 1.最⼤⼦数组和 力扣链接&#xff1a;力扣 给你一个整数数组 nums &#xff0c;请你找出一个…

数据库开发和数据库管理有什么区别?

数据库开发&#xff08;Database Development&#xff09;和数据库管理&#xff08;Database Administration&#xff09;是数据库领域中的两个关键角色和职责。 我这里刚好有嵌入式、单片机、plc的资料需要可以私我或在评论区扣个6 数据库开发人员专注于以下方面&#xff1a…

[RocketMQ] Broker 消息刷盘服务源码解析 (十二)

同步刷盘: 在消息真正持久化至磁盘后RocketMQ的Broker端才会真正返回给Producer端一个成功的ACK响应。异常刷盘: 能够充分利用OS的PageCache的优势, 只要消息写入PageCache即可将成功的ACK返回给Producer端。消息刷盘采用后台异步线程提交的方式进行, 降低了读写延迟和提高了MQ…

chatglm 130B:两个主要的稳定训练方法

解决方案&#xff1a;Qk转置的时候先用单精度来算&#xff0c;softmax的时候再转成FP16 第二个&#xff1a;embeddding 层梯度存在 emdedding层的梯度跟其它层的梯度表示范围相差的非常大&#xff0c;然后会导致这个对损失函数的这个缩放有一定的影响&#xff0c;为了解决这…

MATLAB 基于NDT的点云配准实验(不同参数效果) (25)

MATLAB 基于NDT的点云配准实验(不同参数效果) (25) 一、算法简介二、具体使用1.代码(注释详细)2.结果(不同参数 与ICP比较)一、算法简介 NDT点云配准与ICP一样,都是经典的点云配准算法,这里使用MATLAB进行ndt点云配准,对配准结果进行显示,并尝试不同参数,得到较好…

Spring学习笔记---SpringBoot快速入门

Spring学习笔记---SpringBoot快速入门 Spring学习笔记---SpringBoot1 SpringBoot简介1.1 SpringBoot快速入门1.1.1 开发步骤1.1.1.1 创建新模块1.1.1.2 创建 Controller1.1.1.3 启动服务器1.1.1.4 进行测试 1.1.2 对比1.1.3 官网构建工程1.1.3.1 进入SpringBoot官网1.1.3.2 选择…