文档章节

Java内存模型(主内存&工作内存、volatile、原子性/可见性/有序性)

o
 osc_4nmshwhm
发布于 2018/08/07 12:15
字数 1402
阅读 10
收藏 0

钉钉、微博极速扩容黑科技,点击观看阿里云弹性计算年度发布会!>>>

 

(1)高速缓存

  使读写速度尽可能快

  在多处理器系统中,每个处理器都有自己的高速缓存,而他们又共享统一主存

  缓存中数据不一致问题

  有一些协议

(2)指令重排序

  处理器对输入的代码进行乱序执行优化,处理器在计算之后将乱序执行的结果重组,保证乱序执行的结果和顺序执行的结果是一致的

 

Java内存模型JMM

  主内存(main memory)

  工作内存(working memory)

屏蔽硬件和操作系统的内存访问差异,是Java程序在任何平台下都达到一致性的访问效果

定义变量从内存中取出以及储存到内存的细节

变量指的是共享变量(包括实例字段、静态字段、构成数组的元素,不包括局部变量与方法参数这些线程私有的变量

所有的共享变量都存储在主内存中

每条线程都拥有自己的工作内存

线程的工作内存中保存了当前线程使用到的共享变量的主内存副本拷贝

线程不能直接操作主内存

一个线程也不能访问另一个线程的工作内存

 

主内存和线程工作内存的交互操作

lock unlock(作用于主内存)

read write(主内存)

load store(工作内存)

use assign(工作内存)

上述操作都是原子性的

(1)read之后必须load,store之后必须write(不允许一个变量从主存读取了,但是工作内存不接受;或者一个变量从工作内存发起了回写,但是主存不接受)

(2)不能丢弃assign(不允许一个线程在其工作内存中修改了变量的值,但是又没有同步回主存;也不允许一个线程没有assign变量,但是又想同步回主存)

(3)不允许在工作内存中新建变量(工作内存中use和assign的变量必须是从主从中read并load到的)

(4)同一时刻,只允许一条线程对一个变量进行lock,但是,允许一个线程执行多次lock。每一个lock都必须有与之对应的unlock

(5)在unlock之前,必须把变量同步回主存

 

volatile关键字

JVM提供的轻量级同步策略

(1)可见性:保证主存中的共享变量对所有线程都是可见的,即当一个线程改变了变量的值,其它线程立即可知

  在各个线程的工作内存中,volatile变量可能存在不一致的情况,但是,由于每次使用之前执行引擎都要刷新volatile变量的值,因此看不到不一致的情况

  不能保证原子性(i++)

(2)禁止指令重排序

  内存屏障

  在指令重排序时,不能把内存屏障后面的指令重排序到内存屏障之前

性能:读操作跟普通变量差不多

   写操作慢一些

(1)每次使用(use)volatile变量的时候,都必须先从主内存中load最新的值,用于保证当前线程看见其它线程对共享变量所做的修改

(2)每次修改(assign)volatile变量之后,都必须立即将修改同步回主内存(store),用于保证其它线程能看见当前线程对共享变量所做的修改

(3)禁止指令重排序,代码的执行顺序和程序中定义的顺序是一致的

 

long&double变量

  long和double变量的非原子性协议

  允许虚拟机将没有被volatile修饰的64位数据类型的读写操作分为两次32位的操作进行

  即64位数据类型不用保证read、load、store、write操作的原子性

  

(1)原子性

read load use assign store write 操作都是原子性的

long double类型的特殊规定

(2)可见性

  一个线程对共享变量的修改,其它线程立即可知

  volatile保证可见性:修改数据之后,立即同步回主存;使用数据之前,从主存中刷新最新值

  synchronized保证可见性:对一个变量unlock之前,必须同步回主存

  final保证可见性:final字段在构造器中一旦初始化完成,构造器没有把this引用传递出去,其它线程中就可看见final变量的值

(3)有序性

  在本线程内观察,所有操作都是有序的;但是,在线程外观察,所有操作都是无序的

  线程内表现为串行的语义

  指令重排序

  工作内存和主内存的同步延迟

  volatile保证有序性:禁止指令重排序(内存屏障)

  synchronized保证有序性:同一时刻只允许一条线程获得对象锁

 

内存可见性问题

  指令都是在CPU中执行的,指令在执行过程中进行数据 的读取和写入

  程序执行过程中的临时数据是存放在主存中的

  线程在使用主存中的共享数据时,会复制一份到高速缓存中,对共享数据操作完之后,再将数据写入告诉缓存

  多个线程对共享数据的操作是在线程自己的缓存中进行的,线程之间彼此不可见

  

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
【并发编程】什么是线程安全性?

##线程安全性 线程安全性定义:当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的...

osc_dk3cdlqm
2018/06/19
3
0
Java-内存模型(JSR-133)

Java 内存模型(Java Memory Model,JMM)看上去和 Java 内存结构(JVM 运行时内存结构)差不多,但这两者并不是一回事。JMM 并不像 JVM 内存结构一样是真实存在的,它只是一个抽象的概念。 ...

osc_nubdt7rk
2019/05/29
16
0
知道这些,面试时volatile就稳了

在Java相关的岗位面试中,很多面试官都喜欢考察面试者对Java并发的了解程度,而以volatile关键字作为一个小的切入点,往往可以一问到底,把Java内存模型(JMM),Java并发编程的一些特性都牵...

Java专职小哥
06/16
20
0
求你了,再问你Java内存模型的时候别再给我讲堆栈方法区了…

GitHub 4.1k Star 的Java工程师成神之路 ,不来了解一下吗? GitHub 4.1k Star 的Java工程师成神之路 ,真的不来了解一下吗? GitHub 4.1k Star 的Java工程师成神之路 ,真的确定不来了解一下吗...

osc_eibr31r7
04/16
2
0
深入理解内存模型JMM

JMM(java memory model)java内存模型主要目标是定义程序中的变量,(此处所指的变量是实例字段、静态字段等,不包含局部变量和函数参数,因为这两种是线程私有无法共享)在虚拟机中存储到内...

osc_c0r2dsk1
2018/03/14
2
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周三乱弹 —— 公主是大王的,命是自己的。小怪也要养家糊口啊!

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @巴拉迪维 :郭燕的单曲《下半生》 最近听一些轻快的歌 #今日歌曲推荐# 《下半生》 - 郭燕 手机党少年们想听歌,请使劲儿戳(这里) @锦年 :...

小小编辑
29分钟前
29
0
Git不断提示我输入密码 - Git keeps prompting me for a password

问题: I've been using Git for a while now, but the constant requests for a password are starting to drive me up the wall. 我已经使用Git一段时间了,但是不断要求输入密码的人开始把......

fyin1314
37分钟前
20
0
未捕获ReferenceError:未定义$? - Uncaught ReferenceError: $ is not defined?

问题: How come this code throws an 此代码如何引发 Uncaught ReferenceError: $ is not defined 未捕获的ReferenceError:未定义$ when it was OK before? 以前什么时候可以? $(document......

javail
今天
12
0
263. Ugly Number

题目: 263. Ugly Number 题目地址:https://leetcode.com/problems/ugly-number/ Write a program to check whether a given number is an ugly number. Ugly numbers are positive numbers......

JiaMing
今天
68
0
HCIA_ARP01

ARP(地址解析协议) eNSP 常用路由器:AR2220 常用交换机:S5700、S3700 常用终端:PC、MCS(主播服务器) 设备连线:Copper(以太网用到的双绞线)、Serial(串口线,2SA接口)、Auto(自动连...

创业789
今天
27
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部