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操作)。

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

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就能解决这个问题

JUC并发编程学习笔记(十五)JMM的更多相关文章

  1. JUC并发编程学习笔记

    JUC并发编程学习笔记 狂神JUC并发编程 总的来说还可以,学到一些新知识,但很多是学过的了,深入的部分不多. 线程与进程 进程:一个程序,程序的集合,比如一个音乐播发器,QQ程序等.一个进程往往包含 ...

  2. 并发编程学习笔记(6)----公平锁和ReentrantReadWriteLock使用及原理

    (一)公平锁 1.什么是公平锁? 公平锁指的是在某个线程释放锁之后,等待的线程获取锁的策略是以请求获取锁的时间为标准的,即使先请求获取锁的线程先拿到锁. 2.在java中的实现? 在java的并发包中 ...

  3. Java并发编程学习笔记

    Java编程思想,并发编程学习笔记. 一.基本的线程机制 1.定义任务:Runnable接口 线程可以驱动任务,因此需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现R ...

  4. 并发编程学习笔记(8)----ThreadLocal的使用及源码分析

    1. ThreadLocal的理解 ThreadLocal,顾名思义,就是线程的本地变量,ThreadLocal会为每个线程创建一个本地变量副本,使得使用ThreadLocal管理的变量在多线程的环境 ...

  5. 并发编程学习笔记(4)----jdk5中提供的原子类及Lock使用及原理

    (1)jdk中原子类的使用: jdk5中提供了很多原子类,它会使变量的操作变成原子性的. 原子性:原子性指的是一个操作是不可中断的,即使是在多个线程一起操作的情况下,一个操作一旦开始,就不会被其他线程 ...

  6. python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)

    python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...

  7. 并发编程学习笔记(15)----Executor框架的使用

    Executor执行已提交的 Runnable 任务的对象.此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节.调度等)分离开来的方法.通常使用 Executor 而不是显式地创建 ...

  8. 并发编程学习笔记(14)----ThreadPoolExecutor(线程池)的使用及原理

    1. 概述 1.1 什么是线程池 与jdbc连接池类似,在创建线程池或销毁线程时,会消耗大量的系统资源,因此在java中提出了线程池的概念,预先创建好固定数量的线程,当有任务需要线程去执行时,不用再去 ...

  9. 并发编程学习笔记(13)----ConcurrentLinkedQueue(非阻塞队列)和BlockingQueue(阻塞队列)原理

    · 在并发编程中,我们有时候会需要使用到线程安全的队列,而在Java中如果我们需要实现队列可以有两种方式,一种是阻塞式队列.另一种是非阻塞式的队列,阻塞式队列采用锁来实现,而非阻塞式队列则是采用cas ...

  10. 并发编程学习笔记(11)----FutureTask的使用及实现

    1. Future的使用 Future模式解决的问题是.在实际的运用场景中,可能某一个任务执行起来非常耗时,如果我们线程一直等着该任务执行完成再去执行其他的代码,就会损耗很大的性能,而Future接口 ...

随机推荐

  1. 2022级HAUT新生周赛题解汇总

    2022级HAUT新生周赛(零)题解@:前六题题解  G题比赛模拟题目题解 2022级HAUT新生周赛(一)题解@卞子骏:题解 2022级HAUT新生周赛(二)题解@武其轩:题解  题解2 2022级 ...

  2. Oracle使用SQL截取某字符串

    很多小伙伴在使用Oracle的时候,想通过SQL来提取根据某一字符串截取来获得的字符串,他苦于对SQL不是很熟悉,但是现在你可以放心啦,现在先恭喜你找到了答案.因为在这里我已经为你写好了相关的函数以及 ...

  3. Matlab2021a打包jar包问题(linux、windows)

    都有chatgpt了,实在不想写博客....不过还是记录一下问题吧. 我们在用matlab打包jar包的时候,经常会出现打包出错的问题,但无非注意以下几点就行了: 1.打包方式 这个还是很简单的,而且 ...

  4. 【go语言】1.1.1 Go 语言的历史和背景

    Go 语言,也被称为 Golang,是一种静态强类型.编译型的开源编程语言.Go 语言的出现是为了解决当下的软件开发问题,特别是大规模软件系统的开发. Go 语言的设计者包括 Robert Gries ...

  5. 2021-7-12 VUE的生命周期

    挂载: beforeCreate created beforeMount mounted:el挂载到实例上时运行 更新: beforeUpdate updated 销毁: beforeDestory ...

  6. JS优化技巧,解决冗余代码

    1. 使用箭头函数简化函数定义 // 传统函数定义 function add(a, b) { return a + b; } // 箭头函数简化 const add = (a, b) => a ...

  7. 五 Android Capabilities讲解(转)

    1.Capabilities介绍 可以看下之前代码里面设置的capabilities DesiredCapabilities capabilities = new DesiredCapabilitie ...

  8. Unity的UnityStats: 属性详解与实用案例

    UnityStats 属性详解 UnityStats 是 Unity 引擎提供的一个用于监测游戏性能的工具,它提供了一系列的属性值,可以帮助开发者解游戏的运行情况,从而进行优化.本文将详细介绍 Uni ...

  9. Vue项目打包后放到SpringBoot项目里注意点

  10. SimpleDateFormat 线程安全问题修复方案

    问题介绍 在日常的开发过程中,我们不可避免地会使用到 JDK8 之前的 Date 类,在格式化日期或解析日期时就需要用到 SimpleDateFormat 类,但由于该类并不是线程安全的,所以我们常发 ...