JUC并发编程学习笔记(十五)JMM

JMM

请你谈谈对Volatile的理解

Volatile是java虚拟机提供的轻量级的同步机制

1、保证可见性

2、不保证原子性

3、禁止指令重排

什么是JMM

JVM->java虚拟机

JMM->java内存模型,不存在的东西,概念!约定

关于JMM的一些同步的约定:

  • 线程解锁前,必须把共享变量立刻刷回主存

  • 线程加锁前,必须读取主存中的最小值到工作内存中!

  • 必须要保证加锁和解锁时同一把锁

线程------->工作内存主内存

详见:Java内存模型(JMM)详解 - 程序新视界 - 博客园 (cnblogs.com)

在此交互过程中,Java内存模型定义了8种操作来完成,虚拟机实现必须保证每一种操作都是原子的、不可再拆分的(double和long类型例外)。

  • lock(锁定):作用于主内存的变量,它把一个变量标识为一条线程独占的状态。
  • unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
  • read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用。
  • load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
  • use(使用):作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作。
  • assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
  • store(存储):作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的write操作使用。
  • write(写入):作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中。

Java内存模型还规定了在执行上述8中基本操作时必须满足如下规则。

  • 不允许read和load、store和write操作之一单独出现,即不允许一个变量从主内存读取了但工作内存不接受,或者从工作内存发起回写了但主内存不接受的情况出现。
  • 不允许一个线程丢弃它的最近的assign操作,即变量在工作内存中改变了之后必须把该变化同步回主内存。
  • 不允许一个线程无原因地(没有发生过任何assign操作)把数据从线程的工作内存同步回主内存。
  • 一个新的变量只能在主内存中"诞生",不允许在工作内存中直接使用一个未被初始化(load或assign)的变量,换句话说,就是对一个变量实施use、store操作之前,必须先执行过了assign和load操作。
  • 一个变量在同一时刻只允许一条线程对其进行lock操作,但lock操作可以被同一条线程重复执行多次,多次执行lock后,只有执行相同次数的unlock操作,变量才会被解锁。
  • 如果对一个变量执行lock操作,那将会清空工作内存中此变量的值,在执行引擎使用这个变量前,需要重新执行load或assign操作初始化变量的值。
  • 如果一个变量事先没有被lock操作锁定,那就不允许对它执行unlock操作,也不允许去unlock一个被其他线程锁定住的变量。
  • 对一个变量执行unlock操作之前,必须先把此变量同步回主内存中(执行store、write操作)。

模拟主内存中数据被修改后未能获取到最新数据的子线程的工作内存状态

java 复制代码
package org.example.tvolatile;

import java.util.concurrent.TimeUnit;

public class JMMDemo01 {
    //定义变量
    private static Integer num = 0;
    public static void main(String[] args) throws InterruptedException {
        new Thread(()->{
            //只要num=0就一直循环,来模拟主线程数据被改变后子线程的状态
            while (num==0){

            }
            System.out.println("子线程执行结束,num已经不等于0了");
        }).start();
        //休眠疫苗等待子线程开启
        TimeUnit.SECONDS.sleep(1);
        //修改值
        num=1;
        System.out.println(num);

    }
}

结果就是当主内存中的值已经被改变了,但是子线程中的工作内存不知道,所以还在一直循环

程序一直没有结束!

问题:子线程中的工作内存不知道主内存的值已经被修改过了

------------------>引出Volatile,Volatile就能解决这个问题

相关推荐
JH30737 小时前
SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
java·spring boot·spring
Coder_Boy_8 小时前
技术让开发更轻松的底层矛盾
java·大数据·数据库·人工智能·深度学习
invicinble9 小时前
对tomcat的提供的功能与底层拓扑结构与实现机制的理解
java·tomcat
较真的菜鸟9 小时前
使用ASM和agent监控属性变化
java
黎雁·泠崖9 小时前
【魔法森林冒险】5/14 Allen类(三):任务进度与状态管理
java·开发语言
qq_124987075310 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计
Coder_Boy_10 小时前
基于SpringAI的在线考试系统-考试系统开发流程案例
java·数据库·人工智能·spring boot·后端
Mr_sun.10 小时前
Day06——权限认证-项目集成
java
瑶山11 小时前
Spring Cloud微服务搭建四、集成RocketMQ消息队列
java·spring cloud·微服务·rocketmq·dashboard
abluckyboy11 小时前
Java 实现求 n 的 n^n 次方的最后一位数字
java·python·算法