Java内存模型

Java内存模型(Java Memory Model,JMM)的定义是Java虚拟机试图实现Java程序在各种平台下都能达到一致的内存访问效果。

我们都知道指令的执行是在CPU中进行的,而数据是存放物理内存中的,但是CPU的处理速度一般比内存快的多,于是我们引入高速缓存,它的存储交互很好的解决了CPU与内存之间的矛盾。与此同时摩尔定律表明了单核CPU的主频不可能无限制的增长,要想提升新能,需要多个处理器协同工作,也就是多核。高速缓存和多核的引入,也带来了一些问题:比如缓存一致性问题(当多个处理器运算都涉及到同一块内存区域的时候,就有可能发生缓存不一致的现象)。说到这里,要表达什么呢?在多核系统中,不同系统如何解决高速缓存和多核带来的问题呢,那就是内存模型。内存模型定义了共享内存系统中多线程程序读写操作行为的规范,它保证内存的正确性(可见性、有序性、原子性)。

01

Java内存模型

上面对于内存模型的描述可能会有不正之处,希望大家带着批判的眼光去看这篇文章。

内存模型是为了保证共享内存的正确性,在不同平台上内存模型也是存在差异的,相同的程序在不同平台上,其并发的效果也是不同的。因此Java虚拟机试图定义Java内存模型去屏蔽各种内存和操作系统的内存访问差异,以实现Java程序在各种平台下都能达到一致的内存访问效果。

在JDK1.5发布后,Java内存模型已经成熟和完善起来了。所以我们提到的JMM,一般指的是JDK 5 开始使用的新的内存模型

Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程中是用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行。

线程,工作内存,主内存三者交互关系如图:

JMM就作用于工作内存和主存之间数据同步过程。他规定了如何做数据同步以及什么时候做数据同步。

02

volatile型变量

关于volatile型变量,我们平时听的很多,我们大概都知道被该关键字修饰的变量保证对所有线程的可见性,意思是某一线程修改这个变量的值,对其他线程是可见的,这好像跟我们在上面描述的JMM不同,因为所有变量被线程修改,都是在工作内存中进行的,对于其他线程是不可见的,为什么volatile能打破这个规则呢?实际上一个volatile变量,任意线程都是能看到对这个volatile变量最后的写入。 当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存, 当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效。线程接下来将从主内存中读取共享变量。这就是为什么volatile变量对所有线程可见。

既然volatile型号变量的写操作保证了可见性,那么它是不是就不存在一致性的问题。在Java语言里面运算不是原子操作,在并发情况下volatile同样会出现不安全问题。这是为什么呢?我没想一下i++这个操作,如果两个线程A,B对i执行i++操作,如果线程A从主存中读取i=0进了缓存,然后把数据读入寄存器,之后时间片用完了,然后线程2也从内存中读取i进缓存,因为线程A还未执行写操作,内存屏障是插入在写操作之后的指令,意味着还未触发这个指令,所以缓存行是不会失效的。然后线程2执行完毕,内存中i=1,然后线程1又开始执行,然后将数据写回缓存再写回内存,结果还是1。

所以在不符合以下两条规则的运算场景中,我们仍然要通过加锁来保证原子性:

1.运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值

2.变量不需要与其他的状态变量共同参与不变约束。

本文分享自微信公众号 - 每天学Java(gh_fddfb9d03324),作者:每天学Java

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-01-07

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java线程池分享

    分析一下: T1,T3是多线程本身的带来的开销,希望减少T1,T3所用的时间,从而减少T的时间。如果在程序中频繁的创建或销毁线程,这导致T1和T3在T中占有相...

    每天学Java
  • Java语言中的线程安全

    “ 在深入理解Java虚拟机一书的高效并发部分中提到:按照线程安全的安全程度由强至弱来排序,可以将Java语言中各种操作共享数据分为5类:不可变,绝对线程安全,...

    每天学Java
  • Java真的有引用传递吗?

    经过几天的折腾,小程序总是有了第一版的测试题功能,虽然目前还不够完善,但是测试的效果已经有了,今天上线之后,到目前有二十多人做过测试题。

    每天学Java
  • Java内存模型详解(一)

    其实JMM很好理解,我简单的解释一下,在Java多线程中我们经常会涉及到两个概念就是线程之间是如何通信和线程之间的同步,那什么是线程之间的通信呢,其实就是两个线...

    乱敲代码
  • Java虚拟机--内存模型

    SuperHeroes
  • Java内存模型

    java内存模型(JMM)全称为Java Memory Model,是java虚拟机为了java程序能够正常运行而制定的一套规范,规范中规定了JVM中的数据如何...

    诺浅
  • JVM学习笔记——java内存模型与线程(1)

    多任务处理出现的重要原因是计算机的运算速度与存储及通信子系统的速度差距太大,大量的时间花费在磁盘I/O,数据库访问或者数据库访问上。除了充分利用计算机处理器的能...

    用户1665735
  • java中的内存模型

    现在是资源共享的时代,同样也是知识分享的时代,如果你觉得本文能学到知识,请把知识与别人分享。

    互扯程序
  • 多线程基础(三):synchronized关键字及java内存模型简介

    在前面了解过一些java多线程基础之后,现在,我们用多线程来解决一个实际问题。 假定每个线程可以将一个数字加到100000,现在我们用十个线程,同时相加,看看...

    冬天里的懒猫
  • Java内存模型 - 同步八种操作

    通常意义上的上锁,就是一个线程正在使用时,其他线程必须等待该线程任务完成才能继续执行自己的任务。

    入门小站

扫码关注云+社区

领取腾讯云代金券