基本概念

  • JMM 本身是一种抽象的概念并不是真实存在,它描述的是一组规范,通过这组规范定义了程序的访问方式
  • JMM 同步规定
    • 线程解锁前,必须把共享变量的值刷新回主内存
    • 线程加锁前,必须读取主内存的最新值到自己的工作内存
    • 加锁解锁是同一把锁
  • 由于 JVM 运行程序的实体是线程,而每个线程创建时 JVM 都会为其创建一个工作内存,工作内存是每个线程的私有数据区域,而 Java 内存模型中规定所有变量储存在主内存,主内存是共享内存区域,所有的线程都可以访问,但线程对变量的操作(读取赋值等)必须都工作内存进行
  • 首先要将变量从主内存拷贝的自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存,不能直接操作主内存中的变量,工作内存中存储着主内存中的变量副本拷贝,工作内存是每个线程的私有数据区域,因此不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成

(内存模型图)

三大特性

原子性

public class VolatileDemo {
public static void main(String[] args) {
test01();
} // 测试原子性
private static void test01() {
Data data = new Data();
for (int i = 0; i < 20; i++) {
new Thread(() -> {
for (int j = 0; j < 1000; j++) {
data.addOne();
}
}).start();
}
// 默认有 main 线程和 gc 线程
while (Thread.activeCount() > 2) {
Thread.yield();
}
// 发现不能输出 20000
System.out.println(data.a);
}
} class Data {
volatile int a = 0;
void addOne() {
this.a += 1;
}
}

可见性

public class VolatileDemo {
public static void main(String[] args) {
Data data = new Data();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " coming...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
data.addOne();
System.out.println(Thread.currentThread().getName() + " updated...");
}).start(); // 主线程会进入死循环,说明当有一个线程修改了值,默认不会马上被另一个线程感知到
while (data.a == 0) {
// looping
}
System.out.println(Thread.currentThread().getName() + " job is done...");
}
} class Data {
// int a = 0;
void addOne() {
this.a += 1;
}
}

有序性

    • 计算机在执行程序时,为了提高性能,编译器和处理器常常会对指令做重排,一般分为以下 3 种

      • 编译器优化的重排
      • 指令并行的重排
      • 内存系统的重排
    • 单线程环境里面确保程序最终执行的结果和代码执行的结果一致
    • 处理器在进行重排序时必须考虑指令之间的数据依赖性
    • 多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证用的变量能否一致性是无法确定的,结果无法预测
public class ReSortSeqDemo {
int a = 0;
boolean flag = false; public void method01() {
a = 1; // flag = true;
// ----线程切换----
flag = true; // a = 1;
} public void method02() {
if (flag) {
a = a + 3;
System.out.println("a = " + a);
}
} // 两个线程同时执行method01 和 method02, 如果线程 1 执行 method01 重排序了,然后切换的线程 2 执行 method02 就会出现不一样的结果 }

Java 内存模型(Java Memory Model,JMM)的更多相关文章

  1. Java内存模型(Java Memory Model,JMM)

    今天简单聊聊什么叫做 Java 内存模型,不是 JVM 内存结构哦. JMM 是一个语言级别的内存模型,处理器的硬件模型是硬件级别,Java中的内存模型是内存可见性的基本保证.从而为我们 volati ...

  2. Java 内存模型- Java Memory Model

    多线程越来越多的使用,使得我们需要对它的深入理解.那么就涉及到了Java内存模型JMM.JMM是JVM的一部分,JMM定义了一个线程修改了一个共享变量,其他线程什么时候或者如何看到这个变量,如何去访问 ...

  3. 【深入理解JVM】:Java内存模型JMM

    多任务和高并发的内存交互 多任务和高并发是衡量一台计算机处理器的能力重要指标之一.一般衡量一个服务器性能的高低好坏,使用每秒事务处理数(Transactions Per Second,TPS)这个指标 ...

  4. 全面理解Java内存模型(JMM)及volatile关键字(转载)

    关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoad ...

  5. 全面理解Java内存模型(JMM)及volatile关键字

    [版权申明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) http://blog.csdn.net/javazejian/article/details/72772461 出自[zejian ...

  6. 全面理解Java内存模型(JMM)

    理解Java内存区域与Java内存模型Java内存区域 Java虚拟机在运行程序时会把其自动管理的内存划分为以上几个区域,每个区域都有的用途以及创建销毁的时机,其中蓝色部分代表的是所有线程共享的数据区 ...

  7. java内存结构JVM——java内存模型JMM——java对象模型JOM

    JVM内存结构 Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途.其中有些区域随着虚拟机进程的启动而存在,而有些区 ...

  8. 全面理解Java内存模型(JMM)及volatile关键字(转)

    原文地址:全面理解Java内存模型(JMM)及volatile关键字 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型( ...

  9. 深入理解JMM(Java内存模型) --(一)

    并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信 ...

  10. Java内存模型(JMM)详解

    在Java JVM系列文章中有朋友问为什么要JVM,Java虚拟机不是已经帮我们处理好了么?同样,学习Java内存模型也有同样的问题,为什么要学习Java内存模型.它们的答案是一致的:能够让我们更好的 ...

随机推荐

  1. 记一次因为Gradle与Lombok不兼容导致编译时的内存溢出 Expiring Daemon because JVM heap space is exhausted

    1.现象 版本 Gradel:6.1.1 / 6.5.1 Lombok:1.8.6 / 1.8.10 截图 解决过程 调大idea的堆内存 不行 × idea安装目录中找到 idea64.exe.vm ...

  2. Shell编程—数据展示

    1.标准文件描述符 Linux用文件描述符(file descriptor)来标识每个文件对象.文件描述符是一个非负整数,可以唯一标识会话中打开的文件.每个进程一次 多可以有九个文件描述符.出于特殊目 ...

  3. Swift Expressible literal

    Swift Expressible Literal 引子 从一个面试题说起.有如下代码: struct Book { let name: String } let book: Book = " ...

  4. 设计模式C++模板(Template)模式

    设计模式C++描述----02.模板(Template)模式(转载) 一. 问题 在面向对象系统的分析与设计过程中经常会遇到这样一种情况:对于某一个业务逻辑(算法实现)在不同的对象中有不同的细节实现, ...

  5. Picker 组件的设计与实现

    前言 今天的主题是 Picker 组件的设计与实现,Picker 组件是 NutUI 的一个拾取器组件,它用于显示一系列的值集合,用户可以滚动选择集合中一项,也可以支持多个系列的值集合供用户分别选择. ...

  6. 架构设计 | 基于电商交易流程,图解TCC事务分段提交

    本文源码:GitHub·点这里 || GitEE·点这里 一.场景案例简介 1.场景描述 分布式事务在业务系统中是十分常见的,最经典的场景就是电商架构中的交易业务,如图: 客户端通过请求订单服务,执行 ...

  7. gdb我在我本机上p不了,在别人机子上可以

    gdb我在我本机上p不了,在别人机子上可以,不知道什么 (gdb) p EventFlow->devicetypeThere is no member or method named devic ...

  8. 【NodeJS】-init

    创建NodeJS项目. #新建一个空文件夹 mkdir ReactGame #生成pakeage.json文件(这个文件主要是用来记录这个项目的详细信息的,它会将我们在项目开发中所要用到的包,以及项目 ...

  9. 设置android studio启动时不检查sdk Android studio启动时总是在找AndroidSDK的解决办法

    安装完android studio后,首次启动会弹出检查sdk组件等设置,点击finish会去下载sdk等,如果没有设置代理的情况下,这个界面会卡很久.截图如下: blog0826-1.png 所以, ...

  10. UGUI核心元素、基本控件、复合控件和高级控件

    UGUI的核心元素: Anchor(锚点):每个控件都有一个Anchor属性,控件的4个顶点,分别与Anchor的4个点保持不变的距离,不受屏幕分辨率变化的影响. 系统默认设置控件的Anchor位置在 ...