内存模型

线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory)。

    本地内存中存储了该线程以读/写共享变量的副本。

    不同线程之间无法相互直接访问对方工作内存中的变量,线程间变量值的传递均需要在主内存来完成。

计算机运行过程中数据都是存放在主内存中的:
由于CPU的执行速度非常的快,数据的读取和写入的速度相对较慢,导致CPU执行效率也会大大的降低 当程序在运行过程中,会将运算需要的数据从主内存复制一份到高速缓存中:
后续直接通过高速CPU缓存对数据进行写和读这样,大大的提高了程序的运行速度

可见性 原子性 有序性

可见性:
可见性是指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值 原子性:
不可分割 有序性:
程序执行的顺序按照代码的先后顺序执行 synchronized和Lock保证每个时刻是有一个线程执行同步代码,相当于是让线程顺序执行同步代码,自然就保证了有序性。 volatile关键字来保证一定的“有序性”(防止指令重排) volatile、synchronized 和 final 实现可见性。 synchronized 和在 lock、unlock 中操作保证原子性。 volatile 和 synchronized 两个关键字来保证线程之间操作的有序性。

volatile 关键字

private volatile int account = 100;

可见性:

    b.使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新

    c.因此每次使用该域就要重新计算,而不是使用寄存器中的值 

    d.volatile不会提供任何原子操作,它也不能用来修饰final类型的变量

不能保证它具有原子性(解决:使用AtomicInteger(推荐)或者synchronized ):

    比如 volatile int a = 0;之后有一个操作 a++;

    这个变量a具有可见性,但是a++ 依然是一个非原子操作 

    不会提供任何原子操作,它也不能用来修饰final类型的变量

禁止指令重排:

synchronized关键字的确能保证可见性,为什么还需要volatile关键字保证可见性?(单例模式中双重验证的指令重排问题)

  Singleton singleton = new Singleton()时,这个过程是分步骤的并不是一个原子性的操作,实例化对象其实可以被分为三步:

    1、分配内存空间:memory = allocate();

    2、初始化对象:initInstance(memory);

    3、将instance指向刚刚分配的内存空间:instance = memory

  操作2依赖于操作1,但是操作3并不依赖于操作2,2和3步是可以进行重排序的:

    memory = allocate();    //1:分配对象的内存空间
instance = memory; //3:设置instance指向刚分配的内存地址(此时对象还未初始化)
ctorInstance(memory); //2:初始化对象 在多线程的情况下当一个线程进入执行new操作,其它线程返回的可能是一个还未初始化完全的对象。 其它线程还是可以进行getInstance()方法(错以为Instance已经被实例化出来),
当new操作执行还未全执行完时,其它线程拿到的就是未实例化完全的对象,造成线程不安全。 volatile关键字就能保证是一个完全初始化后的对象(禁止指令重排)。

内存屏障(Memory Barrier)

内存屏障,又称内存栅栏,是一个CPU指令,基本上它是一条这样的指令:
1、保证特定操作的执行顺序。
2、影响某些数据(或者是某条指令的执行结果)的内存可见性。 插入一条Memory Barrier会告诉编译器和CPU:
不管什么指令都不能和这条Memory Barrier指令重排序。 Memory Barrier所做的另外一件事是强制刷出各种CPU cache:
如一个Write-Barrier(写入屏障)将刷出所有在 Barrier 之前写入 cache 的数据,
因此,任何CPU上的线程都能读取到这些数据的最新版本。 volatile是基于Memory Barrier实现的。

JMM 内存模型 与 volatile 关键字的更多相关文章

  1. Java内存模型与volatile关键字

    Java内存模型与volatile关键字 一).并发程序开发 并行程序的开发要涉及多线程.多任务间的协作和数据共享问题. 常用的并发控制:内部锁.重入锁.读写锁.信号量. 二).线程的特点 线程的特点 ...

  2. Java内存模型中volatile关键字的作用

    volatile作用总结: 1. 强制线程从公共内存中取得变量的值,而不是从线程的私有的本地内存中,volatile修饰的变量不具有原子性(修改一个变量的值不能同步). 2. 保证volatile修饰 ...

  3. 基础篇:深入JMM内存模型解析volatile、synchronized的内存语义

    目录 1 java内存模型,JMM(JAVA Memory Model) 2 CPU高速缓存.MESI协议 3 指令重排序和内存屏障指令 4 happen-before原则 5 synchronize ...

  4. Java并发编程:JMM(Java内存模型)和volatile

    1. 并发编程的3个概念 并发编程时,要想并发程序正确地执行,必须要保证原子性.可见性和有序性.只要有一个没有被保证,就有可能会导致程序运行不正确. 1.1. 原子性 原子性:即一个或多个操作要么全部 ...

  5. JMM内存模型相关笔记整理

    JMM 内存模型是围绕并发编程中原子性.可见性.有序性三个特征来建立的 原子性:就是说一个操作不能被打断,要么执行完要么不执行,类似事务操作,Java 基本类型数据的访问大都是原子操作,long 和 ...

  6. Java内存模型与Volatile,Happen-Before原则等

     Java的内存模型 Java内存模型(JMM)是一个抽象的模型.决定了线程主要定义了线程和内存间的抽象关系:主内存存放的是线程共享变量,每个线程有自己的工作内存,存放变量的副本,只能对副本进行读写, ...

  7. Java内存模型:volatile详解

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt202 Java内存模型:volatile是干什么用的Volatile字段是用 ...

  8. JMM内存模型详解(一)

    本文开始死磕JMM(Java内存模型)由于知识点较多,分来写 该文为JMM第一篇 技术往往是枯燥的,本文文字较多 1. JMM是什么? 其实JMM很好理解,我简单的解释一下,在Java多线程中我们经常 ...

  9. JVM学习(七)JMM内存模型

    一.什么是JMM 概念:Java内存模型(Java Memory Model ,JMM)就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能 ...

随机推荐

  1. KiCAD原理图更换库

    KiCAD原理图库更换 将AD的工程文件转换位KiCAD后,打开原理图,系统会自动压缩生成当前工程库,但是这样将原理图复制粘贴到其他地方时,就找不到库了,原理图就会无法显示器件符号,如何将库替换为我们 ...

  2. 添加ali yum源

    wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo #yum clean  a ...

  3. concurrent=false/true的定时任务job策略介绍

    前言: 四种测试情况,cronExpression = 0/30 * * * * ? : 1,一个trigger,job设置的是每30s执行一次,实际需要75s:concurrent=false: 2 ...

  4. 6383. 【NOIP2019模拟2019.10.07】果实摘取

    题目 题目大意 给你一个由整点组成的矩形,坐标绝对值范围小于等于\(n\),你在\((0,0)\),一开始面向\((1,0)\),每次转到后面第\(k\)个你能看到的点,然后将这条线上的点全部标记删除 ...

  5. 二叉堆 与 PriorityQueue

    堆在存储器中的表示是数组,堆只是一个概念上的表示.堆的同一节点的左右子节点都没有规律. 堆适合优先级队列(默认排列顺序是升序排列,快速插入与删除最大/最小值). 数组与堆 堆(完全二叉树)(构造大顶堆 ...

  6. Magento站点优化方案

    Magento 是一个开源电子商务系统,尤其以扩展性高著称,但是很高的扩展性往往是牺牲了速度为代价的,虽然现在magento为速度提升做了很多工作,但是还是没能达到人们对速度的要求.既然如此还是很自然 ...

  7. Vue学习笔记【20】——Vue中的动画(使用动画钩子函数)

    定义及使用钩子函数 定义 transition 组件以及三个钩子函数:  <div id="app">    <input type="button&q ...

  8. vue基础三

    1.模板语法 在底层的实现上, Vue 将模板编译成虚拟 DOM 渲染函数.如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,直接写渲染(render)函数,使用可 ...

  9. 创建一个apk:按钮-click-文字display,测试apk;安装在真机进行调试的方法

    问题引入: 怎么样在一个app做event事件?例如touch操作,滑动操作,和按键事件(back,home等) 回答1:device.touch(x,y) ---获取device对象,然后touch ...

  10. error LNK2001: 无法解析的外部符号 __imp__RegEnumKeyExA@32

    错误: error LNK2001: 无法解析的外部符号 __imp__OpenProcessToken@12 error LNK2001: 无法解析的外部符号 __imp__LookupPrivil ...