美文网首页
jvm内存模型与原子性,可见性,有序性

jvm内存模型与原子性,可见性,有序性

作者: 瓢鳍小虾虎 | 来源:发表于2020-06-18 08:39 被阅读0次

一.内存模型:
每一个线程有一个工作内存,和主存是独立的。
工作内存存放主存重变量的值得拷贝。
线程独享的工作内存和主存的关系,如下图:


image.png

1.当数据从主内存复制到工作存储时,必须出现两个动作:第一,由主内存执行的读(read)操作;第二,由工作内存执行的相应的load操作;
2.当数据从工作内存拷贝到主内存时,也出现两个操作:第一个,由工作内存执行的存储(store)操作;第二,由主内存执行的相应的写(write)操作。
3.每一个操作都是原子的,即执行期间不会被中断,即read不会中断,但是read和load直接会有中断。
4.对于普通变量,一个线程中更新的值,不能马上反应在其他变量中。如果需要在其他线程中立即可见,需要使用 volatile 关键字。


image.png
jmm控制共享变量和共享变量副本直接的拷贝,基于cpu优化的原因,会有一定程度的延迟。

二.原子性:
原子性是指一个操作是不可中断的。即使是在多个线程一起执行的时候,一个操作一旦开始,就不会被其他线程干扰。
i++是原子操作吗?
不是。i++由三个原子操作组成:

  1. 线程私有内存从主存把i的值拷贝下来。
  2. 执行i++操作。
  3. 把i的值赋给主存。

三.可见性
可见性是指当一个线程修改了某一个共享变量的值,其他线程是否能够立即知道这个修改。
编译器优化
硬件优化(如写吸收,批操作)


image.png

这幅图展示了发生可见性问题的一种可能。如果在CPU1和CPU2
volatile:
volatile修饰的变量,在主内存和线程私有内存直接拷贝不会有延迟。


image.png
volatile 不能代替锁
一般认为volatile比锁性能好(不绝对)
选择使用volatile的条件是:语义是否满足应用。
没有volatile -server运行 无法停止,因为VolatileStopThread只在线程的本地存储区查看stop的值。
可见性:一个线程修改了变量,其他线程可以立即知道。

保证可见性的方法:

  1. volatile
  2. synchronized(unlock之前,写变量值回主存)
    3.final(一旦初始化完成,其他线程就可见)

四.有序性:
在并发时,程序的执行可能会出现乱序。
1.在本线程内,操作都是有序的。(不会破坏语义,所以看似有序)
2.在线程外观察,操作都是无序的。(造成原因:1.指令重排。2.主内存同步延迟--可见性)


image.png

线程A首先执行writer()方法
线程B线程接着执行reader()方法
线程B在int i=a+1 是不一定能看到a已经被赋值为1
因为在writer中,两句话顺序可能打乱:
线程A
flag=true
a=1
线程B
flag=true;在a = 1;之前执行。(此时a=0) 就是说flag=true;和a = 1;这两行很难预料谁先执行。
如何保证有序呢:加synchronized同步,同步后,即使做了writer重排,因为互斥的缘故,reader 线程看writer线程也是顺序执行的。


image.png
指令重排:编译器为了使性能优化,编译器会将代码指令的顺序进行调整。保证线程内串行语义,不保证多线程直接的语义。如:
写后读 a=1;b=a; 写一个变量后,再读这个位置。
写后写 a=1;a=2; 写一个变量后,再写这个变量。
读后写 a=b;b=1; 读一个变量后,再写这个变量。
以上语句不能重排。

编译器不考虑多线程间的语义。
可重拍:a=1;b=2;
指令重排的基本原则:
程序顺序原则:一个线程内保证语义的串行性
volatile规则:volatile变量的写,先发生于读
锁规则:解锁(unlock)必然发生在随后的加锁(lock)前
传递性:A指令先于B指令,B指令先于C指令 那么A指令必然先于C指令
线程的start方法先于它的每一个动作
线程的所有操作先于线程的终结(Thread.join())
线程的中断(interrupt())先于被中断线程的代码
对象的构造函数执行结束先于finalize()方法

相关文章

  • java初入多线程5

    volatile 与java内存模型(JMM) java的内存模型都是围绕着原子性、有序性、还有可见性来展开的。 ...

  • jvm

    JAVA内存模型: 有序性、可见性、原子性 导致可见性的原因是缓存,导致有序性的原因是编译优化 涉及 vol...

  • Java内存模型-笔记5

    硬件内存模型 Java内存模型 线程之间通信同步性原则 可能出现的问题可见性原子性有序性 硬件内存模型 工程师为了...

  • volatile和synchronized底层原理

    先来看 JMM java memory model java 内存模型 主要围绕:原子性,可见性,有序性。 A B...

  • Java内存模型&DCL双锁检测

    Java内存模型 内存模型是为了保证共享内存的正确性(可见性、有序性、原子性),其定义了共享内存系统中多线程程序读...

  • 《实战高并发程序设计》读书笔记-线程基本知识补充

    volatile   Java内存模型都是围绕着原子性、有序性和可见性展开的,为了在适当的场合,确保线程间的有序性...

  • 多线程下指令重排与DCL单列模式

    指令重排简述 1、JMM内存模型三大特性包括原子性,可见性,有序性。详细请看关于Java内存模型的三大特性 2、指...

  • 聊一聊Java内存模型

    之前提到的原子性、可见性、有序性都与Java内存模型(JMM)密不可分。在Java内存模型中定义了主内存和线程的工...

  • jvm内存模型与原子性,可见性,有序性

    一.内存模型: 每一个线程有一个工作内存,和主存是独立的。 工作内存存放主存重变量的值得拷贝 线程独享的工作内存和...

  • jvm内存模型与原子性,可见性,有序性

    一.内存模型:每一个线程有一个工作内存,和主存是独立的。工作内存存放主存重变量的值得拷贝。线程独享的工作内存和主存...

网友评论

      本文标题:jvm内存模型与原子性,可见性,有序性

      本文链接:https://www.haomeiwen.com/subject/lmxhxktx.html