Java内存模型

转载:http://www.cnblogs.com/leesf456/p/5291484.html

Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model, JMM)来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。


1、Java并发基础

在并发编程中存在两个关键问题:(1) 线程之间如何通信;(2)线程之间如何同步

1.1 通信

通信是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:共享内存消息传递

共享内存:在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信。

消息传递:在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送消息来显式进行通信。

1.2 同步

同步是指程序用于控制不同线程之间操作发生相对顺序的机制。

在共享内存并发模型里,同步是显式进行的。程序员必须显式指定某个方法或某段代码需要在线程之间互斥访问。

在消息传递的并发模型里,由于消息的发送必须在消息的接收之前, 因此同步是隐式进行的。

Java并发采用的是共享内存模型,通信隐式进行;同步显示指定。

Java同步的三种方式:(1)volatile、(2)锁、(3)final


2、Java内存模型

Java内存模型JMM(Java Memory Model)主要目标是定义程序中各个变量(非线程私有)的访问规则,即在虚拟机中将变量存储到内存和从内存取出变量这样的底层细节。

Java中每个线程都有自己私有的工作内存。工作内存保存了被该线程使用的变量的主内存副本拷贝,线程对变量的读写操作都必须在自己的工作内存中进行,无法直接读写主内存中的变量。两个线程无法直接访问对方的工作内存。

2.1 线程、工作内存、主内存关系

理解线程、工作内存、主内存之间的关系时,我们可以类比物理机中CPU、高速缓存、内存之间关系。

CPU、高速缓存、主内存之间的关系如下:

这里写图片描述

线程、工作内存、主内存的关系如下

这里写图片描述

若线程A要与线程B通信(访问变量)。首先,线程A把工作内存中的共享变量的值刷新到主内存中;然后,线程B从主内存中读取更新过的变量的值到自己的工作内存中。

2.2 内存间通信的指令

内存间通信,主要指线程私有的工作内存与主内存之间的通信,如线程间共享变量的传递。主要有如下操作。


这里写图片描述
这里写图片描述

read、load操作;store、write操作必须按顺序执行(并非连续执行)。

上述的8个操作需要满足如下规则:

这里写图片描述

2.3 重排序

在执行程序时为了提高性能,编译器和处理器常常会对指令做重排序。重排序会遵守数据的依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。重排序分为如下三种类型。

  1. 编译器优化的重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序。

  2. 指令级并行的重排序。现代处理器采用了指令级并行技术(Instruction-Level Parallelism, ILP)来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。

  3. 内存系统的重排序。由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。

而我们编写的Java源程序中的语句顺序并不对应指令中的相应顺序,如(int a = 0; int b = 0;翻译成机器指令后并不能保证a = 0操作在b = 0操作之前)。因为编译器、处理器会对指令进行重排序,通常而言,Java源程序变成最后的机器执行指令会经过如下的重排序。


这里写图片描述

2.4 内存屏障指令

为了保证内存可见性,Java编译器在生成指令序列的适当位置会插入内存屏障指令来禁止特定类型的处理器重排序。内存屏障指令分为如下四种:

这里写图片描述

2.5 先行发生原则(happens-before)

先行发生原则是判断数据是否存在竞争、线程是否安全的主要依据。

如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在 happens-before 关系,如果操作A先行发生与操作B,即A操作产生的结果能够被操作B观察到。

具体的 happens-before 原则如下

  1. 程序顺序规则:在一个线程内,按照程序代码顺序,书写在前面的操作先行发生于书写在后面的操作(控制流操作而不是程序代码顺序)。

  2. 管程锁定规则:一个unlock操作先行发生于后面对同一个锁的lock操作。

  3. volatile变量规则:对一个 volatile变量的写操作,先行发生于后面对这个变量的读操作。

  4. 线程启动规则:Thread对象的start()方法先行发生于此线程的每一个动作。

  5. 线程终止规则:线程中所有操作都先行发生于对此线程的终止检测。

  6. 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生。

  7. 对象终结规则:一个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法的开始。

  8. 传递性:如果操作A先行发生于操作B,且操作B先行发生于操作C,那么操作A先行发生于操作C。

说明:happens-before 仅仅要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二个操作之前(可能会发生指令重排)。时间先后顺序与happens - before原则之间没有太大的关系。

2.6 as-if-serial 语义

as-if-serial 的语义是:

不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。编译器,runtime 和处理器都必须遵守 as-if-serial 语义。为了遵守 as-if-serial 语义,编译器和处理器不会对存在数据依赖关系的操作做重排序,因为这种重排序会改变执行结果。但是,如果操作之间不存在数据依赖关系,这些操作就可能被编译器和处理器重排序。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容