Java内存模型——可见性】的更多相关文章

/** * 可见性问题 * @author Snway * */public class Visibility {        private static boolean stop;        public static void main(String[] args) throws Exception {        Thread t1 = new Thread(new Runnable(){            public void run() {               …
1.Java HotSpot JVM运行时数据区 Java内存模型即Java Memory Model,简称JMM.JMM定义了Java 虚拟机(JVM)在计算机内存(RAM)中的工作方式.JVM是整个计算机虚拟模型,所以JMM是隶属于JVM的. 如果我们要想深入了解Java并发编程,就要先理解好Java内存模型.Java内存模型定义了多线程之间共享变量的可见性以及如何在需要的时候对共享变量进行同步.原始的Java内存模型效率并不是很理想,因此Java1.5版本对其进行了重构,现在的Java8仍…
Java内存模型JMM与可见性 标签(空格分隔): java 1 何为JMM JMM:通俗地讲,就是描述Java中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取变量这样的底层细节. 结合上图,先介绍几个概念: 主内存:保存了所有的变量. 共享变量:如果一个变量被多个线程使用,那么这个变量会在每个线程的工作内存中保有一个副本,这种变量就是共享变量. 工作内存:每个线程都有自己的工作内存,线程独享,保存了线程用到了变量的副本(主内存共享变量的一份拷贝).工作内存负责…
JVM运行时内存结构回顾 在JVM相关的介绍中,有说到JAVA运行时的内存结构,简单回顾下 整体结构如下图所示,大致分为五大块 而对于方法区中的数据,是属于所有线程共享的数据结构 而对于虚拟机栈中数据结构,则是线程独有的,被保存在线程私有的内存空间中,所以这部分数据不涉及线程安全的问题 不管是堆还是栈,他们都是保存在主内存中的 线程堆栈包含正在执行的每个方法的所有局部变量(调用堆栈上的所有方法).线程只能访问它自己的线程堆栈. 由线程创建的局部变量对于创建它的线程以外的所有其他线程是不可见的.…
此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 注:本文主要参考自<深入理解Java虚拟机(第二版)>和<深入理解Java内存模型> 1.Java内存模型(JMM) Java内存模型的主要目标:定义在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节. 注意:上边的变量指的是共享变量(实例字段.静态字段.数组对象元素),不包括线程私有变量(局部变量.方法参数),因为私有变量不会存在竞争关系. 1.1.内存模型就是一张图: 说明: 所…
注:本文主要参考自<深入理解Java虚拟机(第二版)>和<深入理解Java内存模型> 1.Java内存模型(JMM) Java内存模型的主要目标:定义在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节. 注意:上边的变量指的是共享变量(实例字段.静态字段.数组对象元素),不包括线程私有变量(局部变量.方法参数),因为私有变量不会存在竞争关系. 1.1.内存模型就是一张图: 说明: 所有共享变量存于主内存 每一条线程都有自己的工作内存(就是上图所说的本地内存) 工作内存中保存…
Java内存模型 VS JVM运行时数据区 首先Java内存模型(JMM)和JVM运行时数据区并不是一个东西,许多介绍Java内存模型的文章描述的堆,方法区,Java虚拟机栈,本地方法栈,程序计数器这东西并不是Java内存模型的内容而是JVM运行时数据区的内容.要理解二者的区别就要了解<Java虚拟机规范>和<Java语言规范>.我们知道Java虚拟机上并不知只有Java语言,像JRuby, ,Scala,Kotlin,Groovy等也都运行在Java虚拟机上,而这些语言想要在Ja…
什么是 Java 内存模型? 导致可见性的原因是缓存,导致有序性的原因是编译优化,那解决可见性. 有序性最直接的办法就是禁用缓存和编译优化,但是这样问题虽然解决了,我们程序的性能可就堪忧了.   合理的方案应该是按需禁用缓存以及编译优化.那么,如何做到“按需禁用”呢?对于并发程序,何时禁用缓存以及编译优化只有程序员知道,那所谓“按需禁用”其实就是指按照程序员的要求来禁用.所以,为了解决可见性和有序性问题,只需要提供给程序员按需禁用缓存和编译优化的方法即可.   Java 内存模型是个很复杂的规范…
      一.原子性 原子性操作指相应的操作是单一不可分割的操作.例如,对int变量count执行count++d操作就不是原子性操作.因为count++实际上可以分解为3个操作:(1)读取变量count的当前值:(2)拿count的当前值和1做加法运算:(3)将加完后的值赋给count变量. 在多线程环境中,非原子操作可能会受其他线程的干扰.比如,上述例子如果没有对相应的代码进行同步(Synchronization)处理,则可能出现在执行第2个操作的时候,count变量的值已经被其他线程修改…
本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 前言 之前的文章中讲到,JMM是内存模型规范在Java语言中的体现.JMM保证了在多核CPU多线程编程环境下,对共享变量读写的原子性.可见性和有序性. 本文就具体来讲讲JMM是如何保证共享变量访问的可见性的. 什么是可见性问题 我们从一段简单的代码来看看到底什么是可见性问题. public class VolatileDemo { boolean sta…
JMM(Java Memory Model)内存模型之可见性 JMM是Java内存模型的缩写,本身是一种抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式. JMM关于同步的规定 线程解锁前,必须把共享变量的值刷新会主内存 线程加锁前,必须读取主内存的最新值到自己的工作内存 加锁解锁是同一把锁 由于JVM运行程序的实体是线程,而每个线程创建是JVM都会为其创建一个工作内存(有些地方称作栈空间),工作内存是每…
前言 解决并发编程中的可见性和有序性问题最直接的方法就是禁用CPU缓存和编译器的优化.但是,禁用这两者又会影响程序性能.于是我们要做的是按需禁用CPU缓存和编译器的优化. 如何按需禁用CPU缓存和编译器的优化就需要提到Java内存模型.Java内存模型是一个复杂的规范.其中最为重要的便是Happens-Before规则.下面我们先介绍如何利用Happens-Before规则解决可见性和有序性问题,然后我们再扩展简单介绍下Java内存模型以及我们前篇文章提到的重排序概念. volatile 在前一…
Java内存模型就是一种符合内存模型规范的,屏蔽了各种硬件和操作系统的访问差异的,保证了Java程序在各种平台下对内存的访问都能保证效果一致的机制及规范. Java内存模型是根据英文Java Memory Model(JMM)翻译过来的.其实JMM并不像JVM内存结构一样是真实存在的.他只是一个抽象的概念.JSR-133: Java Memory Model and Thread Specifification中 描述了,JMM是和多线程相关的,他描述了一组规则或规范,这个规范定义了一个线程对共…
文题 "跬步千里" 主要是为了凸显这篇文章的基础性与重要性(狗头),并发编程这块的知识也确实主要围绕着 JMM 和三大性质来展开. 全文脉络如下: 1)为什么要学习并发编程? 2)为什么需要并发编程? 3)介绍 Java 内存模型 4)详解 Java 内存模型的三大性质(原子性.可见性.有序性),这也是判断线程安全的三个重要指标.以原子性为例,大致行文逻辑如下: 什么是原子性 不满足原子性会导致什么问题 如何保证原子性 为什么要学习并发编程 对于 "我们为什么要学习并发编程?…
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: 为什么学习Java的内存模式 缓存一致性问题 什么是内存模型 JMM(Java Memory Model)简介 volatitle关键字 原子性 可见性 有序性 指令重排 先行发生——happen-before原则 解释执行和编译执行 其他语言(c和c++)也有内存模型么? 为什么需要关注Java内存模型?   之前有一个我实习的同事(已经工作的)反讽我:学(关注)这个有什么用? 我没有回答,我牢记一句话…
在并发编程中,多个线程之间采取什么机制进行通信(信息交换),什么机制进行数据的同步? 在Java语言中,采用的是共享内存模型来实现多线程之间的信息交换和数据同步的. 线程之间通过共享程序公共的状态,通过读-写内存中公共状态的方式来进行隐式的通信.同步指的是程序在控制多个线程之间执行程序的相对顺序的机制,在共享内存模型中,同步是显式的,程序员必须显式指定某个方法/代码块需要在多线程之间互斥执行. 在说Java内存模型之前,我们先说一下Java的内存结构,也就是运行时的数据区域: Java虚拟机在执…
概要 文章是<深入理解Java内容模型>读书笔记,该书总共包括了3部分的知识. 第1部分,基本概念 包括"并发.同步.主内存.本地内存.重排序.内存屏障.happens before规则.as-if-serial规则.数据依赖性.顺序一致性模型.JMM的含义和意义". 第2部分,同步机制 该部分中就介绍了"同步"的3种方式:volatile.锁.final.对于每一种方式,从该方式的"特性"."建立的happens befo…
原文地址:http://www.codeceo.com/article/java-memory-6.html 与前面介绍的锁和Volatile相比较,对final域的读和写更像是普通的变量访问.对于final域,编译器和处理器要遵守两个重排序规则: 在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序. 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序. 下面,我们通过一些示例性的代码来分别说…
原文地址:http://www.codeceo.com/article/java-memory-4.html Volatile的特性 当我们声明共享变量为volatile后,对这个变量的读/写将会很特别.理解volatile特性的一个好方法是:把对volatile变量的单个读/写,看成是使用同一个监视器锁对这些单个读/写操作做了同步.下面我们通过具体的示例来说明,请看下面的示例代码: class VolatileFeaturesExample { volatile long vl = 0L; /…
原文地址:http://www.codeceo.com/article/java-memory-3.html 数据竞争与顺序一致性保证 当程序未正确同步时,就会存在数据竞争.java内存模型规范对数据竞争的定义如下: 在一个线程中写一个变量, 在另一个线程读同一个变量, 而且写和读没有通过同步来排序. 当代码中包含数据竞争时,程序的执行往往产生违反直觉的结果(前一章的示例正是如此).如果一个多线程程序能正确同步,这个程序将是一个没有数据竞争的程序. JMM对正确同步的多线程程序的内存一致性做了如…
原文地址:http://www.codeceo.com/article/java-memory-1.html 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递. 在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信.在消息传递的并发模型里,线程之间没有公共状态,线程之间…
Java内存模型规范了Java虚拟机与计算机内存是如何协同工作的.Java虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型——又称为Java内存模型. 如果你想设计表现良好的并发程序,理解Java内存模型是非常重要的.Java内存模型规定了如何和何时可以看到由其他线程修改过后的共享变量的值,以及在必须时如何同步的访问共享变量. 原始的Java内存模型存在一些不足,因此Java内存模型在Java1.5时被重新修订.这个版本的Java内存模型在Java8中人在使用. Java内…
1. 概述 多任务和高并发是衡量一台计算机处理器的能力重要指标之一.一般衡量一个服务器性能的高低好坏,使用每秒事务处理数(Transactions Per Second,TPS)这个指标比较能说明问题,它代表着一秒内服务器平均能响应的请求数,而TPS值与程序的并发能力有着非常密切的关系.在讨论Java内存模型和线程之前,先简单介绍一下硬件的效率与一致性. 2.硬件的效率与一致性 由于计算机的存储设备与处理器的运算能力之间有几个数量级的差距,所以现代计算机系统都不得不加入一层读写速度尽可能接近处理…
翻译自wiki百科:https://en.wikipedia.org/wiki/Java_memory_model 没找到直接在wiki上编辑中文的页面,我就在这翻译下,自己学习用. java内存模型描述了线程在java编程中如何和内存交互.连同单线程执行代码描述,这个内存模型提供java编程语言的含义. 原始的java内存模型是在1995年发展的,被广泛看作破坏,阻止很多运行时的优化的并且对代码安全不提供足够强的保证的. 环境 java 编程语言和平台提供线程功能.线程之间的同步对开发者很难理…
什么是Java内存模型 Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽掉各种硬件和操作系统的访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果.在此之前,主流程序语言(如C/C++等)直接使用物理硬件和操作系统的内存模型,因此,会由于不同平台上内存模型的差异,有可能导致程序在一套平台上并发完全正常,而在另外一套平台上并发访问却经常出错,因此在某些场景下就不许针对不同的平台来编写程序. Java内存模型即要定义得足够严谨,才能…
与前面介绍的锁和 volatile 相比较,对 final 域的读和写更像是普通的变量访问.对于final 域,编译器和处理器要遵守两个重排序规则: 在构造函数内对一个 final 域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序. 初次读一个包含 final 域的对象的引用,与随后初次读这个 final 域,这两个操作之间不能重排序. 下面,我们通过一些示例性的代码来分别说明这两个规则: public class FinalExample { int i; /…
volatile 的特性 当我们声明共享变量为 volatile 后,对这个变量的读/写将会很特别.理解 volatile 特性的一个好方法是:把对 volatile 变量的单个读/写,看成是使用同一个锁对这些单个读/写操作做了同步.下面我们通过具体的示例来说明,请看下面的示例代码: class VolatileFeaturesExample { //使用volatile声明64位的long型变量 volatile long vl = 0L; public void set(long l) {…
数据竞争与顺序一致性保证 当程序未正确同步时,就会存在数据竞争.java 内存模型规范对数据竞争的定义如下: 在一个线程中写一个变量, 在另一个线程读同一个变量, 而且写和读没有通过同步来排序. 当代码中包含数据竞争时,程序的执行往往产生违反直觉的结果(前一章的示例正是如此).如果一个多线程程序能正确同步,这个程序将是一个没有数据竞争的程序. JMM 对正确同步的多线程程序的内存一致性做了如下保证: 如果程序是正确同步的,程序的执行将具有顺序一致性(sequentially consistent…
基础 并发编程模型的分类 在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体).通信是指线程之间以何种机制来交换信息.在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递. 在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信.在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送消息来显式进行通信. 同步是指程序用于控制不同线程之间操作发生相对顺序的机制.在共享内…
提纲挈领地说一下Java内存模型: 什么是Java内存模型 Java内存模型定义了一种多线程访问Java内存的规范.Java内存模型要完整讲不是这里几句话能说清楚的,我简单总结一下Java内存模型的几部分内容: (1)Java内存模型将内存分为了 主内存和工作内存 .类的状态,也就是类之间共享的变量,是存储在主内存中的,每次Java线程用到这些主内存中的变量的时候,会读一次主内存中的变量,并让这些内存在自己的工作内存中有一份拷贝,运行自己线程代码的时候,用到这些变量,操作的都是自己工作内存中的那…