[JVM-4]Java内存模型(JMM)
Java 内存模型
屏蔽掉各种硬件和操作系统的内存访问差异。
1 主内存和工作内存之间的交互
2 对于 volatile 型变量的特殊规则
关键字 volatile 是 Java 虚拟机提供的最轻量级的同步机制。
一个变量被定义为 volatile 的特性:
保证此变量对所有线程的可见性。但是操作并非原子操作,并发情况下不安全。
如果不符合 运算结果并不依赖变量当前值,或者能够确保只有单一的线程修改变量的值 和 变量不需要与其他的状态变量共同参与不变约束 就要通过加锁(使用 synchronize 或 java.util.concurrent 中的原子类)来保证原子性。
禁止指令重排序优化。
通过插入内存屏障保证一致性。
3 对于 long 和 double 型变量的特殊规则
Java 要求对于主内存和工作内存之间的八个操作都是原子性的,但是对于 64 位的数据类型,有一条宽松的规定:允许虚拟机将没有被 volatile 修饰的 64 位数据的读写操作划分为两次 32 位的操作来进行,即允许虚拟机实现选择可以不保证 64 位数据类型的 load、store、read 和 write 这 4 个操作的原子性。这就是 long 和 double 的非原子性协定。
4 原子性、可见性与有序性
回顾下并发下应该注意操作的那些特性是什么,同时加深理解。
原子性(Atomicity)
由 Java 内存模型来直接保证的原子性变量操作包括 read、load、assign、use、store 和 write。大致可以认为基本数据类型的操作是原子性的。同时 lock 和 unlock 可以保证更大范围操作的原子性。而 synchronize 同步块操作的原子性是用更高层次的字节码指令 monitorenter 和 monitorexit 来隐式操作的。
可见性(Visibility)
是指当一个线程修改了共享变量的值,其他线程也能够立即得知这个通知。主要操作细节就是修改值后将值同步至主内存(volatile 值使用前都会从主内存刷新),除了 volatile 还有 synchronize 和 final 可以保证可见性。同步块的可见性是由“对一个变量执行 unlock 操作之前,必须先把此变量同步会主内存中( store、write 操作)”这条规则获得。而 final 可见性是指:被 final 修饰的字段在构造器中一旦完成,并且构造器没有把 “this” 的引用传递出去( this 引用逃逸是一件很危险的事情,其他线程有可能通过这个引用访问到“初始化了一半”的对象),那在其他线程中就能看见 final 字段的值。
有序性(Ordering)
如果在被线程内观察,所有操作都是有序的;如果在一个线程中观察另一个线程,所有操作都是无序的。前半句指“线程内表现为串行的语义”,后半句是指“指令重排”现象和“工作内存与主内存同步延迟”现象。Java 语言通过 volatile 和 synchronize 两个关键字来保证线程之间操作的有序性。volatile 自身就禁止指令重排,而 synchronize 则是由“一个变量在同一时刻指允许一条线程对其进行 lock 操作”这条规则获得,这条规则决定了持有同一个锁的两个同步块只能串行的进入。
5 先行发生原则
也就是 happens-before 原则。这个原则是判断数据是否存在竞争、线程是否安全的主要依据。先行发生是 Java 内存模型中定义的两项操作之间的偏序关系。
天然的先行发生关系
- 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作;
- 锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作;
- volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作;
- 线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作;
- 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生;
- 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行;
- 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始;
- 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C;
[JVM-4]Java内存模型(JMM)的更多相关文章
- Java内存模型JMM与可见性
Java内存模型JMM与可见性 标签(空格分隔): java 1 何为JMM JMM:通俗地讲,就是描述Java中各种变量(线程共享变量)的访问规则,以及在JVM中将变量存储到内存和从内存中读取变量这 ...
- 多线程并发之java内存模型JMM
多线程概念的引入是人类又一次有效压寨计算机的体现,而且这也是非常有必要的,因为一般运算过程中涉及到数据的读取,例如从磁盘.其他系统.数据库等,CPU的运算速度与数据读取速度有一个严重的不平衡,期间如果 ...
- Java内存模型JMM 高并发原子性可见性有序性简介 多线程中篇(十)
JVM运行时内存结构回顾 在JVM相关的介绍中,有说到JAVA运行时的内存结构,简单回顾下 整体结构如下图所示,大致分为五大块 而对于方法区中的数据,是属于所有线程共享的数据结构 而对于虚拟机栈中数据 ...
- 【JVM】Java内存模型
原文:多线程之Java内存模型(JMM)(一) 概述 多任务和高并发是衡量一台计算机处理器的能力重要指标之一.一般衡量一个服务器性能的高低好坏,使用每秒事务处理数(Transactions Per S ...
- 全面理解Java内存模型(JMM)及volatile关键字(转载)
关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型(@Annotation) 深入理解Java类加载器(ClassLoad ...
- 全面理解Java内存模型(JMM)及volatile关键字(转)
原文地址:全面理解Java内存模型(JMM)及volatile关键字 关联文章: 深入理解Java类型信息(Class对象)与反射机制 深入理解Java枚举类型(enum) 深入理解Java注解类型( ...
- 什么是Java内存模型(JMM)
什么是java内存模型 缓存一致性问题 在现代计算机中,因为CPU的运算速度远大于内存的读写速度,因此为了不让CPU在计算的时候因为实时读取内存数据而影响运算速度,CPU会加入一层缓存,在运算之前缓存 ...
- 对多线程java内存模型JMM
多线程概念的引入体现了人类重新有效压力寨计算机.这是非常有必要的,由于所涉及的读数据的过程中的一般操作,如从磁盘.其他系统.数据库等,CPU计算速度和数据读取速度已经严重失衡.假设印刷过程中一个线程将 ...
- Java内存模型(JMM)详解
在Java JVM系列文章中有朋友问为什么要JVM,Java虚拟机不是已经帮我们处理好了么?同样,学习Java内存模型也有同样的问题,为什么要学习Java内存模型.它们的答案是一致的:能够让我们更好的 ...
- Java并发编程:Java内存模型JMM
简介 Java内存模型英文叫做(Java Memory Model),简称为JMM.Java虚拟机规范试图定义一种Java内存模型来屏蔽掉各种硬件和系统的内存访问差异,实现平台无关性. CPU和缓存一 ...
随机推荐
- Java 位运算符和 int 类型的实现
Java 位运算符和 int 类型的实现 其他运算符 # 算术运算符 +.-.*./.++i.i++.--i.i-- # 关系运算符 ==.!=.>.<.>=.<= # 逻辑运 ...
- php二维数组根据某个字段去重
php的二维数组根据某个字段去重,在这默认为二维数组的结构是一样的,现在根据二维数组里的id字段去重,把id相同的重复的元素去掉 /** * 二维数组根据某个字段去重 * @param array $ ...
- Django学习开发--笔记一(从零开始)
创建django项目注: 首先需在python中下载django 命令:pip install django1.任意文件中创建django项目 diango-admin startproject my ...
- SQLServer之创建嵌套触发器
嵌套触发器创建规则 当触发器执行启动其他触发器的操作时,DML 和 DDL 触发器都是嵌套触发器. 这些操作都可以启动其他触发器等. DML 触发器和 DDL 触发器最多可以嵌套 32 层. 可以通过 ...
- JDBC获得连接时报connection refused
1,检查数据库服务器的IP是否正确. 2,检查用户名密码是否正确. 3,检查SID,获selecte instance_name from v$instance;
- 推荐一套Angular2的UI模板
Core UI Core UI是一款基于Bootstrap4的UI模板,有html.angular2,react和vue版.我是在使用angular2版本中发现其项目结构不符合angular风格指南推 ...
- CSS---选择器种类 | 层叠性权重
一.css选择器种类 1.1,ID选择器 1.2,类选择器 1.3,标签选择器 1.4,后代选择器 1.5,子代选择器 1.6,交集选择器 1.7,并集选择器 1.8,通配符选择器 1.9,属性选择器 ...
- 模块简介:(random)(xml,json,pickle,shelve)(time,datetime)(os,sys)(shutil)(pyYamal,configparser)(hashlib)
Random模块: #!/usr/bin/env python #_*_encoding: utf-8_*_ import random print (random.random()) #0.6445 ...
- .NET CORE学习笔记系列(2)——依赖注入[4]: 创建一个简易版的DI框架[上篇]
原文https://www.cnblogs.com/artech/p/net-core-di-04.html 本系列文章旨在剖析.NET Core的依赖注入框架的实现原理,到目前为止我们通过三篇文章从 ...
- velocity模板引擎 -- java.io.FileNotFoundException: velocity.log (Permission denied)
问题原因是velocity的日志框架导致(velocity是使用自己封装的日志框架记录日志的),velocity在初始化Logger时,如果没有读取到配置文件,则会使用默认的velocity.log做 ...