JAVA内存模型与线程以及volatile理解

Wesley13
• 阅读 683

Java内存模型是围绕在并发过程中如何处理原子性、可见性、有序性来建立的。

一、主内存与工作内存
  Java内存模型主要目标是在虚拟机中将变量存储到内存和从内存中取出变量。这里的变量包括:实例字段、静态字段、构成数组对象的元素;不包括局部变量和方法参数,因为它们是线程私有的。
Java内存模型规定了所有变量都存储在主内存,线程的工作内存保存该线程使用的变量的主内存副本拷贝。线程对变量的所有读取、赋值操作在工作内存中进行,不能直接读写主内存中的变量。不同线程之间的变量值传递在主内存中进行。
主内存主要对应于Java堆中的对象实例,工作内存主要对应于虚拟机栈中的部分区域。
线程、主内存、工作内存三者交互关系:

JAVA内存模型与线程以及volatile理解

二、内存间的交互操作
lock(锁定):作用于主内存的变量,把一个变量标识为一条线程独占状态 。
unlock(解锁):作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
read(读取):作用于主内存变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用。
load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个需要使用变量的值的字节码指令时将会执行这个操作。
assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋值给工作内存的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作。
write(写入):作用于主内存的变量,它把store操作从工作内存中一个变量的值传送到主内存的变量中。
这八种基本操作的规则:
  不允许read和load、store和write操作之一单独出现。
  不允许一个线程丢弃它的最近assign的操作,即变量在工作内存中改变了之后必须同步到主内存中。
  不允许一个线程无原因地(没有发生过任何assign操作)把数据从工作内存同步回主内存中。
  一个新的变量只能在主内存中诞生,不允许在工作内存中直接使用一个未被初始化(load或assign)的变量。即就是对一个变量实施use和store操作之前,必须先执行过了assign和load操作。
  一个变量在同一时刻只允许一条线程对其进行lock操作,lock和unlock必须成对出现。
  如果对一个变量执行lock操作,将会清空工作内存中此变量的值,在执行引擎使用这个变量前需要重新执行load或assign操作初始化变量的值。
  如果一个变量事先没有被lock操作锁定,则不允许对它执行unlock操作;也不允许去unlock一个被其他线程锁定的变量。
  对一个变量执行unlock操作之前,必须先把此变量同步到主内存中(执行store和write操作)。
三、对volatile变量的特殊规则
  volatile是轻量级的同步机制。一个变量定义为volatile时,具备的特性:
1、此变量对所有线程的可见性,也就是一个线程修改了这个变量的值,新的值对其他线程来说是可以立即发现的。新的值能立即同步到主内存,每次使用前立即从主内存刷新。
2、禁止指令重排序。

volatile DCL单例模式实例:

/**
 * @author monkjavaer
 * @date 2018/12/04 22:37
 */
public class Singleton {

    private volatile static Singleton instance;

    public static Singleton getInstance(){
        if (instance ==null){
            synchronized (Singleton.class){
                if (instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) {
        Singleton.getInstance();
    }
}

参考资料:
https://www.infoq.cn/article/ftf-java-volatile
https://www.ibm.com/developerworks/cn/java/j-jtp06197.html
《深入理解Java虚拟机》

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
灯灯灯灯 灯灯灯灯
3年前
一次性带你了解清楚Java内存模型!
Java内存模型咳咳咳,能看完的都是人上人。。。。Java虚拟机内部使用JMM(Java内存模型)将内存划分为两个逻辑单元,线程栈(或者叫本地内存)和堆。每一个线程都有属于自己的线程栈,在线程栈中会保存局部变量(也叫做本地变量)、方法中定义的参数和异常处理器的参数(catch中的参数);这些参数和变量都属于线程局部操作,会被隔离,所以不受内存模
红烧土豆泥 红烧土豆泥
3年前
(转载)Java内存区域(运行时数据区域)和内存模型(JMM) - czwbig
转载自:Java内存区域和内存模型是不一样的东西,内存区域是指Jvm运行时将数据分区域存储,强调对内存空间的划分。而内存模型(JavaMemoryModel,简称JMM)是定义了线程和主内存之间的抽象关系,即JMM定义了JVM在计算机内存(RAM)中的工作方式,如果我们要想深入了解Java并发编程,就要先理解好Java内存模型。Java
Wesley13 Wesley13
3年前
Java 内存模型
什么是Java内存模型?JMM(JavaMemoryModel,Java内存模型),它定义了多线程访问Java内存的规范。简单的说有以下几部分内容:Java内存模型将内存分为主内存和工作内存定义了几个原子操作,用于操作主内存和工作内存中的变量定义了volatile变量的使用规则happensbefor
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
Java多线程之内存可见性
Java多线程之内存可见性一、Java内存模型介绍什么是JMM?Java内存模型(JavaMemoryModel)描述了Java程序中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的细节所有的变量都存储在主内存中每个线程都
Wesley13 Wesley13
3年前
Java 多线程:volatile关键字
概念volatile也是多线程的解决方案之一。\\volatile能够保证可见性,但是不能保证原子性。\\它只能作用于变量,不能作用于方法。当一个变量被声明为volatile的时候,任何对该变量的读写都会绕过高速缓存,直接读取主内存的变量的值。如何理解直接读写主内存的值:回到多线程生成的原因(Java内存模型与
Wesley13 Wesley13
3年前
Java内存模型详解
内存模型(memorymodel)内存模型描述的是程序中各变量(实例域、静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存取出变量这样的低层细节.不同平台间的处理器架构将直接影响内存模型的结构.在C或C中,可以利用不同操作平台下的内存模型来编写并发程序.但是,这带给开发人员的是,更高的学习成本.相
待兔 待兔
5个月前
Java内存的可见性
Java内存的可见性可见性:一个线程对共享变量的修改,能够及时被其它线程看到共享变量:如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量Java内存模型(JMM):描述了Java程序中各种线程共享变量的访问规则,以及在JVM