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

news2024/11/25 22:55:06

一、Java 内存模型

JMM即Java Memory Model,他定义了主存(共享的数据)工作内存(私有的数据)抽象概念,底层对应着CPU寄存器、缓存、硬件内存、CPU指令优化等

JMM体现以下几个方面

  • 原子性-保证指令不会受到线程上下文切换的影响
  • 可见性-保证指令不会受cpu缓存的影响
  • 有序性-保证指令不会受cpu指令并行优化的影响

二、可见性

现在有个run共享变量为true,主线程在sleep,子线程在while循环条件为run为true,然后主线程醒了就run变false,但是我们发现子线程还在运行。

因为Java把内存分为了主存和共享内存

初始状态,t1线程刚开始从主存读取了run的值到工作内存,

因为t要频繁的从出内存中读取run的值,JIT编译器会将run的值缓存到自己工作内存中的高速缓存(工作内存的底层关联了cpu缓存),减少对主存中run的访问,提高效率

1秒后main改了run但是t1线程是从自己的缓存中拿的,所以不知道

解决方案:

volatile(易变关键字)

用来修饰成员变量静态成员变量(局部不可以),就表示这个是变量是从主存中拿取,避免现场从自己工作缓存中查找变量的值,必须到主存中获取,线程操作volatile变量就是直接操作主存

synchronized也可以解决,但是要上monitor操作系统的锁,性能更差

其实在死循环中加入System.out.println也能让停止

    private void newLine() {
        try {
            synchronized (this) {
                ensureOpen();
                textOut.newLine();
                textOut.flushBuffer();
                charOut.flushBuffer();
                if (autoFlush)
                    out.flush();
            }
        }
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        }
    }

因为print方法加了synchronized关键字(当然println也加了,换行操作也会持有锁)
而synchronized方法也是能保证了该同步块中的变量的可见性的,所以下次stop从主存中读出false就跳出了while。
这里记录一下synchronized做的操作:
1、获得同步锁;
2、清空工作内存;
3、从主内存拷贝对象副本到工作内存;
4、执行代码(计算或者输出等);
5、刷新主内存数据;
6、释放同步锁。
总结一句话:sychronized可以保证变量的可见性

可见性和原子性

前面的例子就是可见性,保证多个线程之间,一个线程对volatile变量的修改对另一个线程可见,不能保证原子性,只有一个线程写,多个线程读的时候,这个情况很适合volatile。

synchronized既可以保证原子性,也可以保证可见性。但缺点是synchronized重量级操作,性能相对比较低。

三、有序性

JVM会在不影响正确性的前提下调整语句的执行顺序,这种JVM自己调整执行顺序的操作叫指令重排。但在多线程下指令重拍可能会影响正确性。

指令重排在多线程下可能存在问题

比如上面这种情况,线程2是给num赋值,然后ready为true就唤醒线程1,这个时候如果指令重排了,先执行换标记,然后唤醒了,最后才赋值就会出问题了,他就会直接用0的值

 

想要保证不会出现指令重排就再ready变量加上volatile,他可以保证他前面的指令是顺序执行的

四、volatile原理

volatile的底层实现原理是内存屏障,Memory Barrier

  • 对volatile变量的写指令后会加入写屏障
  • 对volatile变量的读指令后会加入读屏障

 1、可见性保证

写屏障保证在该屏障之前的,对共享变量的改动,都同步到主存中。这样别的线程就都能看到最终同步到主存的数据,从而避免了指令重排的问题。

而读屏障保证在该屏障后,对共享变量的读取,加载的是主存中的最新数据,意思是读取的时候不会读自己本地的,而是去主存中读取

2、有序性保证

写屏障会保证指令重排的时候,不会把写屏障之前的代码排在写屏障之后,他前面的一定是在他前面写入主存的。

读屏障会保证指令重排的时候,不会让读屏障之后的代码排在读屏障的前面先读

注意:有序性的保证只能保证本线程内相关代码不被重排序

五、线程安全的单例

判断是否为null和new这个步骤可能有线程安全问题,所以要加syn,他是进来先判断有没有的,没有才创建,所以也叫懒惰初始化

但是这样做可能有问题,就是我每次都要加syn进来判断是不是为null,这个上锁是有开销的,如果第一次创建成功后,后面的判断都是不成功还要加锁很浪费性能

这个时候我们就可以用双重判断,外面加一个if来判断是不是null,如果不是null都不用加锁了

但是这样可以有问题:指令重排的问题,在字节码文件的时候有空new对象构造器构造和给INSTANCE赋值的顺序变化,如果先赋值但是还构造的时候,别人判断到这个对象已经被赋值了不为null所以直接return这个没构造好的对象了

虽然说synchronized可以保证对象的有序性,但是前提是要让synchronized完全管理这个对象,但是现在这个INSTANCE这个对象是放到外面的,synchronized只是赋值

解决方案:

其实就是在INSTANCE这个变量上加个volatile就行了

因为volatile会加写屏障,他可以保证他之前的指令一定在前面执行,所以这个赋值前必须先构造,所以赋值的时候一定被构造了。

问题:

单例的类为什么要加final?

因为final的类不能别继承,如果子类实现了这个类然后重写方法,重写可能会破坏单例

如果实现了序列化接口,还要做什么防止返序列化来破坏单例?

对象的创建不一定是通过new来创建的,如果我们实现了序列化接口,我们反序列化的时候,也会创建新对象,其实解决就是加上一个readResovle方法,反序列化会调用,直接返回这个对象就可以了不反序列字节码的那个结果

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ad18报错:Minimum Solder Mask Sliver Constraint

报告上提示: Minimum Solder Mask Sliver (Gap0.254mm) (All),(All) Minimum Solder Mask Sliver Constraint,PCB焊盘阻焊层之间间距小于0.254报错 修改了这里,把这个报警值改小一些,就不会报警了 翻译过来是:最小…

8.vue3医疗在线问诊项目 - _问诊室模块-websocket学习 ==> 消息卡片、websocket、socket.io、约定通讯规则、建立连接

8.vue3医疗在线问诊项目 - _问诊室模块-websocket学习 > 消息卡片、websocket、socket.io、约定通讯规则、建立连接 问诊室-路由与组件 目标:配置路由和分析结构 1)路由配置 {path: /room,component: () > import(/views/room/index.vue)…

UNIX网络编程卷一 学习笔记 第二十章 广播

本书迄今为止的所有例子都是单播:一个进程与另一个进程通信。TCP只支持单播寻址,而UDP和原始IP还支持其他寻址类型,下图比较了不同的寻址方式: IPv6往寻址体系中增加了任播(anycasting)方式。RFC 1546讲述…

章节5:04-shiro反序列化漏洞

章节5:04-shiro反序列化漏洞 复现环境 本地tomcat或Docker vulhub 基础环境: IDEA Maven Tomcat Burp JDK8版 01 Shiro介绍 Shiro Apache Shiro:开源安全框架 身份验证授权会话管理加密 本地代码 https://github.com/apache/shi…

Iptables防火墙策略

目录 一、iptables netfilter/iptables 关系 二、四表五链 三、iptables的安装 iptables 命令行配置方法 管理选项 一、iptables Linux 系统的防火墙——netfilter/iptables IP信息包过滤系统,它实际上由两个组件netfilter 和 iptables组成。 主要工作在网络…

MATLAB与大数据:如何应对海量数据的处理和分析

第一章:引言 在当今数字化时代,大数据已经成为了各行各业的核心资源之一。海量的数据源源不断地涌现,如何高效地处理和分析这些数据已经成为了许多企业和研究机构面临的重要挑战。作为一种功能强大的数学软件工具,MATLAB为我们提供…

深度剖析InnoDB存储结构

大家都知道 MySQL 的数据都是存储在物理磁盘上的,那具体是保存在哪个文件呢?我们首先要知道MySQL 存储的行为是由存储引擎实现的,不同的存储引擎保存的文件自然也不同。由于InnoDB 是我们常用的存储引擎,也是 MySQL 默认的存储引擎…

Spring Cloud Alibaba - Sentinel源码分析(二)

目录 一、Sentinel源码分析 1、时间窗算法 2、滑动时间窗算法 3、Sentinel滑动时间窗口算法源码解析 4、Sentinel滑动窗口数据统计源码解析 一、Sentinel源码分析 1、时间窗算法 时间窗算法,也可以称之为:固定时间窗算法 概念:固定时…

015:vue项目中常用的正则表达式

第015个 查看专栏目录: VUE — element UI 专栏目标 在vue和element UI联合技术栈的操控下,本专栏提供行之有效的源代码示例和信息点介绍,做到灵活运用。 (1)提供vue2的一些基本操作:安装、引用,模板使用…

【RV1126】使用gpiolib框架

文章目录 史上最简单:增加GPIO控制功能是如何实现的呢?GPIOLIB框架Linux 驱动实现 控制引脚输出高低电平综合测试 这一套非常方便! 史上最简单:增加GPIO控制功能 如果是想增加GPIO控制只需要修改设备树就可以做到! …

谷粒商城第二天-项目环境搭建

目录 一、前言 二、学习的内容 一、虚拟平台的安装,远程连接虚拟机的工具的安装 二、Docker以及常用软件的安装 一、安装Docker: 二、安装相关软件 三、开发环境的统一 1. 这里就是调整Maven的下载依赖的地址,改用阿里云镜像地址 2. …

11.vue3医疗在线问诊项目 - _药品订单 ==> 支付页面、支付详情、支付结果、订单详情、物流信息、高德地图工具

11.vue3医疗在线问诊项目 - _药品订单 > 支付页面、支付详情、支付结果、订单详情、物流信息、高德地图工具 药品订单-支付页面-路由 目标:配置路由,分析药品支付组件结构 1)路由与组件 {path: /medicine/pay,component: () >…

系列十一、MongoDB副本集

一、概述 MongoDB副本集(Replica Set)是有自动故障恢复功能的主从集群,有一个Primary节点和一个或者多个Secondary节点组成。副本集没有固定的主节点,当主节点发生故障时,整个集群会选举一个主节点 为系统提供服务以保…

大数据测试基本知识

常用大数据框架结构 1.大数据测试常用到的软件工具 工具推荐,对于测试数据构造工具有:Datafaker、DbSchema、Online test data generator等;ETL测试工具有:RightData、QuerySurge等;数据质量检查工具:great…

SpringBoot医药管理系统设计+第三稿+文档

博主介绍:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 项目名称 SpringBoot医药管理系统设计第三稿文档 视频演示 SpringBoot医药管理系统设计第三稿中期检查表ppt外文文献翻译文献综述开题任务书查重报告安装视频讲…

【计算机网络】第五章数据链路层-电子科技大学2023期末考试

第五章 数据链路层 学习目的 目的1:理解链路层服务的主要功能 差错检查、纠错 共享广播信道:多点接入问题(multiple access) 链路层寻址(link layer addressing) 局域网技术:Ethernet, VLANs 目的2:链路层技术的实现 点到点…

【Java入门】-- Java基础详解之【程序控制结构】

目录 1.程序流程控制介绍 2.顺序控制 3.分支控制if-else 4.嵌套分支 5.switch分支语句 6.for循环控制(重点) 7.while循环控制 8.do...while循环控制 9.多重循环控制(重难点!) 10.跳转控制语句break 11.跳转…

计算机课程个性化内容推荐系统的设计与实现+文档等

博主介绍:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 项目名称 计算机课程个性化内容推荐系统的设计与实现文档等 视频演示 计算机课程个性化内容推荐系统的设计与实现 系统介绍 计算机课程个性化内容推荐系统的设…

Car Guide

文章目录 科目一第一章 机动车驾驶证申领和使用规定第一节 驾驶证的许可?种类和有效期第二节 驾驶证的申领第三节 驾驶证的使用第四节 驾驶考试第五节 违法记分制度 第二章 交通信号第一节 交通信号灯第二节 交通标志第三节 交通标线第四节 交警手势 第三章 道路交通…

Ansible之playbooks剧本

目录 一、playbooks1、playbooks简述2、playbooks剧本格式3、playbooks组成部分4、playbooks启动 二、playbook编写 apache 的yum安装部署剧本三、playbook编写 nginx 的yum安装并且能修改其监听端口的剧本四、 playbook的定义、引用变量1、基础变量的定义与引用2、引用fact信息…