【JavaEE】——内存可见性问题

举报
三三是该溜子 发表于 2025/05/05 10:42:52 2025/05/05
【摘要】 ​阿华代码,不是逆风,就是我疯,你们的点赞收藏是我前进最大的动力!!希望本文内容能够帮助到你!目录一:内存可见性问题一:内存可见性问题内存可见性引起的多线程安全问题(一个线程读,一个线程写)package thread;import java.util.Scanner;/**Created with IntelliJ IDEA.Description:User: Hua YYDate: 20...


阿华代码,不是逆风,就是我疯,你们的点赞收藏是我前进最大的动力!!希望本文内容能够帮助到你!

目录

一:内存可见性问题

一:内存可见性问题
内存可见性引起的多线程安全问题(一个线程读,一个线程写)

package thread;

import java.util.Scanner;

/**

  • Created with IntelliJ IDEA.

  • Description:

  • User: Hua YY

  • Date: 2024-09-23

  • Time: 10:50
    */
    public class ThreadDemon26 {
    public static int flag = 0;

    public static void main(String[] args) {

     Thread t1 = new Thread(()->{
         while(flag == 0){//等待t1线程输入flag的值,只要不为0就能结束t1线程
    
         }
         System.out.println("t1线程结束");
     });
     Thread t2 = new Thread(()->{
         System.out.println("请输入flag的值");
         Scanner scanner = new Scanner(System.in);
         flag = scanner.nextInt();
     });
    
     t1.start();
     t2.start();
    

    }
    }
    1:代码解释
    这段代码想要表现出来的效果是,t1,t2线程同时运行,通过t2线程中输入的flag的值来控制t1线程是否结束。

例如:t2线程给flag赋值,输入一个1,那么此时t1线程就不会进入while循环,打印t1线程结束。输入0,那t1线程就陷入死循环

2:结果分析
上文我们先后输入了1,0,2…都没能使t1线程结束,这是为什么呢?

(1)指令拆解
while(flag == 0){};

这条语句其实有两个指令

①load
cpu从内存中读取flag的值(load)到cpu的寄存器上(开销很大)

②访问寄存器
cpu访问寄存器中存储的flag的值,与0进行比较(条件跳转指令)(开销低)

(此处不理解load和为什么开销很大,请看阿华写的前面的文章哈,有详细解释)

(2)指令分析
重点条件:①中load的操作(读内存),相较于②中访问寄存器的操作,开销大的多。

3:JVM代码优化
在我们编译完代码后,JVM会在保持你代码逻辑不变的前提下,对你写过的代码进行智能分析,并进行优化。

这个保持你代码逻辑不变的条件其实很苛刻,单线程还好,但是遇到多线程就难免会遇到一些bug。

我们上述的代码就是t2修改了内存,但是t1并没有看到,这就叫“内存可见性问题”

4:解决问题
(1)引入.sleep()
治标不治本,加入sleep,load的循环次数减少,JVM优化的迫切程度就会降低

(2)volatile
volatile关键字,是强制性关闭优化,保证每次循环都会从内存中读取数据。开销是变大了,但是数据更准了

功能①:保证内存可见性,每次访问变量都要读取内存,而不是优化到寄存器或者缓存器当中

功能②:禁止指令重排序,对于被volatile修饰的变量的操作指令,是不能被重排序的

(3)JMM模型准确描述
我们的描述:在上述代码中,编译器发现,每次循环都要读取读取内存,开销太大,于是就把读取内存操优化为读取寄存器操作。

JMM模型描述:在上述代码中,编译器发现,每次循环都要读取“主内存”,开销太大,于是就把“主内存”中的数据拷贝到“工作内存”中,后续每次读取都是到“工作内存”中。

注:在JMM模型当中,“主内存”对标内存,“工作内存”对标寄存器+缓存哪一套,之所以这么叫是因为方便跨平台使用。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。