共享模型之内存

news2024/11/18 16:55:27

JMM

JMM:Java内存模型。定义了主存(所有线程共享的数据)、工作内存(每个线程对应的私有数据)的抽象概念。

JMM存在以下几个特征

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

可见性

public class test{
    static boolean run = true;
    public static void main(String[] args){
        new Thread(()->{
            while(run){
                //……
            }
        }).start();

        System.out.println("主线程结束子线程");
        run = false;
    }
}

主线程结束子线程

理论上来讲,当run改为false后,子线程也会跟着结束并结束程序运行。但是实际并不会结束程序,因此主线程结束并不会让子线程结束while循环。

这就是可见性一个体现,不受CPU缓存影响。从JMM解释来看。

解决方案

将run变量使用volatile(异变)关键词修饰。这样就不会从缓存区获取run值,而是从主存中获取。

volatile关键词用来修饰成员变量与静态成员变量,修饰局部变量没意义,因为局部变量是线程私有的,主存中都没带存的。

或是使用synchroized加锁后来修改run的值。因为synchroized在进入保护的代码前会废弃工作内存重新再去主存中读取。[拓展:synchronized在获取锁之前需要去主存中获取保护代码块所需要的变量存储在工作内存中,当释放锁时会将工作内存中的变量刷新到主存中]。

volatile只能解决可见性问题,并不能解决指令交错的问题,因此只适用于一个线程写多个线程读的场景,比如说两个线程分别进行i++与i--,并不能保证能够正常得出结果。

synchronized虽然可以解决原子性与可见性的问题但是属于重量级操作,性能比较低。

有序性

JVM在不影响程序运行的正确性的前提下,会进行指令重排。在多线程下可能会存在安全隐患。

一般情况下赋值操作,是不在乎谁先谁后,因此可以进行指令重排的。但是在多线程下,有时需要使用这些变量,那么可能会存在安全隐患。

public class demo6 {
    static int num;
    static boolean ready;
    static int result;

    public static void main(String[] args) {
        //线程1
        new Thread(() -> {
            if (ready) {
                result = num + num;
            } else {
                result = 1;
            }
        }).start();

        new Thread(() -> {
            num = 2;
            ready = true;
        }).start();
    }
}

对以上代码进行分析,原则上num与ready的赋值操作先后顺序是无所谓的。但是此时还存在线程1使用这两个变量,这两个变量的结果会对result的结果产生影响。

  • 结果1:result值为1,此结果是因为先对num赋值又或是没有赋值,此时ready为false,走了线程1中的else代码。
  • 结果2:result值为4,此结果是因为线程2对两个值进行了赋值后,线程1才进行执行走的是if中的代码。
  • 结果3:result值为0,此结果是对ready赋值后,但是num还没有进行赋值去执行线程1中的if中代码,导致result值为0。

以上是指令重排序带来的危害,无法预测程序的运行结果,禁止指令重排只需要对ready变量使用volatile修饰即可。

如何保证可见性

写屏障:在volatile修饰的变量之前包括volatile变量,对于共享变量的变动会同步到主存。

读屏障:对于volatile变量之后的变量读取需要从主存中读取。

如何保证有序性

写屏障:在指令重排序时,不会将写屏障之前的代码排序到写屏障之后。

读屏障:在指令重排序时,不会将读屏障之后的代码排序到读屏障之前。

写屏障只能保证能够读取到最新的数据,并不能解决指令交错的问题。有序性只能保重本线程中的代码不会被指令排序

关于单例模式中双重检查锁出现的问题

通过查看创建对象部分的字节码文件来看

前两行是获取单例对象并进行非空判断的字节码,如果不为空则跳转37处。这是第一层if判断

从6到36部分,是synchronized部分字节码,意思是获取类对象,复制一份存储在字符常量池中加锁,获取单例对象判断是否为空,为空则创建出一个对象,复制一份地址,根据地址调用构造器(21)后对单例对象进行复制后解锁,如果不为空跳转到37处。

问题在于21与24可能通过指令重排序后互换位置。那么在多线程中可能出现以下问题

线程2拿到了没有初始化的值去使用,造成空指针异常。

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

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

相关文章

C语言—什么是数组名

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int arr[]{1,2,3,4};printf("%p\n",arr);printf("%p\n",&arr);printf("%p\n",*arr);return 0; } 结论&#xff1a;数组名是数组首元素地址&#xff08;下标为0的元素…

PC端从零搭建微信自动回复机器人(一)基础框架搭建及源码

由于工作需要&#xff0c;最近一年一直在研究和使用C#&#xff0c;加上最近工作上有做微信机器人的需要&#xff0c;在已经对接、调试稳定之后&#xff0c;将项目的源码分享给大家&#xff0c;传递开源精神。 一、环境依赖 1、开发工具&#xff1a;Vistual Studio 2022 2、Ne…

【FFmpeg视频解码】解码数据结构及函数总结

转载自原文地址&#xff1a;https://www.cnblogs.com/wangguchangqing/p/5744941.html 本文的总结分为以下两个部分&#xff1a; 数据读取&#xff0c;主要关注在解码过程中所用到的FFmpeg中的结构体。解码过程中所调用的函数 在学习的过程主要参考的是dranger tutorial&…

从零开始搭建博客网站-----源代码试部署

拿到了该项目的源码&#xff0c;先尝试是否可以成功部署&#xff0c;详细的部署视频地址 后端项目部署 先把maven配置好&#xff0c;都改成自己下载的maven地址 文件编码改成utf-8&#xff0c;防止配置文件乱码 如果maven是刚下的&#xff0c;要改一下下载包的地址&#xff0…

使用信息面板沟通研发工作

凌鲨里面的内容面板里面有专门针对研发团队的白板功能&#xff0c;它可以把文档&#xff0c;图片&#xff0c;软件设计&#xff0c;需求&#xff0c;任务/缺陷等相关研发要素串接起来。 使用 你还可以调整背景颜色。 引用项目内数据 点击面板中的连接会在右侧打开对应内容

电子学会C/C++编程等级考试2021年12月(二级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:统计指定范围里的数 给定一个数的序列S,以及一个区间[L, R], 求序列中介于该区间的数的个数,即序列中大于等于L且小于等于R的数的个数。 时间限制:1000 内存限制:65536输入 第一行1个整数n、,分别表示序列的长。(0 < n…

浅谈建筑节能监管平台在高校能源管理中的实践与应用

安科瑞 华楠 摘要&#xff1a;以节约型校园建设示范工程———宁夏大学节能监管平台项目建设为例&#xff0c;对系统的总体构架、关键技术、管理软件功能进行了详细的介绍。同时针对项目建设、运行和管理过程中出现的一些问题&#xff0c;提出有针对性的解决措施&#xff0c;为…

模拟退火算法应用——求解一元函数的最小值

仅作自己学习使用 一、问题 需求&#xff1a; 计算函数 的极小值&#xff0c;其中个体x的维数n10&#xff0c;即x(x1,x2,…,x10)&#xff0c;其中每一个分量xi均需在[-20,20]内。因此可以知道&#xff0c;这个函数只有一个极小值点x (0,0,…,0)&#xff0c;且其极小值是0&…

信息检索指标直接优化的通用近似框架

1、直接优化信息检索指标的背景 1.1、存在问题 直接优化信息检索的指标是信息检索的一大方向。主要包含两类方法&#xff0c;一类是将IR指标作为上界进行优化&#xff1b;另一类是使用平滑函数近似表示IR指标进行优化。 直接优化IR指标方式很自然&#xff0c;但没有提供理论…

【ArcGIS Pro微课1000例】0037:ArcGIS Pro中模型构建器的使用---以shp批量转kml/kmz为例

文章目录 一、ArcGIS Pro模型构建器介绍二、shp批量转kml/kmz1. 打开模型构建器2. 添加工作空间4. 添加【创建要素图层】工具5. 添加【图层转kml】工具6. 输出文件命名7. 运行模型一、ArcGIS Pro模型构建器介绍 模型构建器是一种可视化编程语言,用于构建地理处理工作流。 地理…

Inport 模块

文章目录 Interpolate datainport 模块存在于模型最顶层Port Dimension 和 Variable-size signal Interpolate data Interpolate data&#xff1a;当将 Workspace 的数据导人模型时, 对没有对应数据点的采样时刻进行线性插值的开关选项。 inport 模块存在于模型最顶层 inpo…

区块链技术将如何影响未来的数字营销?

你是否听腻了区块链和数字营销等流行语&#xff0c;却不明白它们对未来意味着什么&#xff1f;那么&#xff0c;准备好系好安全带吧&#xff0c;因为区块链技术将彻底改变我们对数字营销的看法。从建立消费者信任到提高透明度和效率&#xff0c;其可能性是无限的。 让我们来探…

3.10-容器的操作

这一节讲解一下对于container我们可以进行哪些操作&#xff1f; 可以使用以下命令来停止正在运行的Docker容器&#xff1a; docker container stop <CONTAINER ID> 关于运行中的容器&#xff0c;我们可以进行的操作&#xff1a; 第一个是docker exec命令&#xff0c;这个…

软件开发中的抓大放小vs极致细节思维

最近在开发过程中&#xff0c;遇到了好多次 “这个需求点这次要不要做&#xff1f;” 的问题&#xff0c; 主要有两方阵营&#xff0c;比如以研发主导的 “这次先不做、等必要的时候再做” &#xff0c;另外一方是以PM主导的 “这个不做需求不完整&#xff0c;可能影响用户体验…

单片机AT89C51直流电机控制电路PWM设计

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;直流电机 获取论文报告源码源程序原理图 此文将介绍一种直流电机&#xff0c;详细阐述了用单片机输出口所给占空比的不同实现电机的调速的设计方法&#xff1b;着重讨论L298用于电机驱动时特有的优势。直流电机调速具有…

影刀RPA_boss直聘翻页(避坑)

boss直聘翻页这里有个坑 问题&#xff1a; 无限循环中&#xff0c;点击下一页按钮&#xff0c;直到不可点击为止。 发现&#xff0c;在点到第5页的时候&#xff0c;再次点击下一页&#xff0c;直接就点击了页码10&#xff0c;导致流程直接就结束了。 在第5页进行校验&#xff0…

基于51单片机的百叶窗控制系统设计

**单片机设计介绍&#xff0c; 基于51单片机的百叶窗控制系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于51单片机的百叶窗控制系统设计可以分为硬件设计和软件设计两个方面。下面是一个简要的设计介绍&#xff1a; …

阿里云服务器安装mysql数据库之后无法远程连接

目录 一、mysql安装完成后直接远程远程连接阿里云服务器上的MySQL会报下述错误&#xff1a; 1、修改root用户的host 为% 登录MySQL 后 执行 2、修改完成后执行 3、退出mysql 重启mysql服务 exit; 4、修改完成后需要设置阿里云的安全规则。 二、dbaver测试链…

C语言每日一题(37)两数相加

力扣网 2 两数相加 题目描述 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&a…

【Spring篇】Spring注解式开发

本文根据哔哩哔哩课程内容结合自己自学所得&#xff0c;用于自己复习&#xff0c;如有错误欢迎指正&#xff1b; 我在想用一句话激励我自己努力学习&#xff0c;却想不出来什么惊为天人、精妙绝伦的句子&#xff0c;脑子里全是上课老师想说却没想起的四个字 “ 唯手熟尔 ”&am…