当前位置: 首页 > news >正文

java 内存模型书籍_那些年读过的书《Java并发编程实战》十、再探究Java内存模型...

1、什么是内存模型,为什么需要它?

(1)内存模型的发展背景

近几年计算性能通过重排序实现了很大的提升,而且处理器也越来越朝着多核处理器发展以实现硬件的并行性。随着处理器的不断强大,编译器也在不断的改进:通过指令重排序来实现优化执行,使用成熟的全局寄存器分配

算法。这些都使得线程在内存内的操作更趋于复杂,如果没有正确的同步机制下,内存间的操作呈现乱序执行,从而不能保证计算结果的正确性。

编译器重排序:使得编译后的指令顺序可以和源代码的顺序不一样

处理器重排序:在编译器重排序的基础上再进行指令的优化重排序

处理器的并行性:多线程内线程之间的操作执行顺序不同,要实现线程间的数据共享在没有同步的机制下易产生不安全的数据共享。

处理器的多级缓存:如果缓存提交至主内存的顺序没有一定的同步机制下,就会出现提交顺序的乱序,使得共享数据在内存的不可见性。

a82469e332f99586961cde4cdfecf3bc.png

1)对单线程程序执行的影响 在指令重排序的情况下,只要保证最终的计算结果和严格的串行执行环境下的结果一致下,重排序等优化措施是可以的。

2)对多线程程序执行的影响 多线程中线程间各自的操作执行顺序不同,强行保持程序的串行性,只会增加线程间的调度次数,而频繁的线程调度会引起不要的上下文操作使得线程的开销很大也降低了程序的执行速度。在只需要进行数据共享的操作内使

用同步机制协调线程间的操作,实现线程间的数据共享(保存线程间短暂的串行性)就能够减少不要的性能开销。

(2)Java内存模型是处理器架构内存模型的抽象 Java内存模型屏蔽了不同处理器架构内存模型之间的差异(JVM通过插入内存栅栏来屏蔽JMM与底层平台内存模型之间的差异)

(3)重排序 1)进行重排序的条件:操作之间不存在偏序关系和全序关系

2)禁止重排序的方法:锁,volatile,final

重排序会破外操作之间的偏序关系(Happens-Before),从而产生数据竞争问题

(4)内存模型简介 1)简介:

Java内存模型是通过各种操作来定义的,包括对变量的读写操作,监视器的加锁和释放操作,以及现场的启动和合并操作。

Java内存模型实质是为最终计算结果的正确性,而采取的实现内存操作间保存偏序关系即实现内存操作的有序性,实现内存操作的内存可见性和原子性的内存访问操作的模型

2)偏序关系(Happens-Before):

偏序关系(Happens-Before)的本质:保证操作之间的内存可见性

保持偏序关系(Happens-Before)的准则: 规则名称 内容 说明

程序顺序规则 程序代码顺序自然保持操作间的偏序关系

监视器锁规则 在同一个锁上锁的释放肯定在锁的获取之后

volatile规则 volatile变量的写操作肯定在volatile变量的读操作之前

线程启动规则 线程的启动操作start肯定在线程执行操作之前

线程结束规则 线程执行的任何操作肯定在线程检测到该线程结束之前执行,或者从join操作或者调用Thread.isAlive是返回

中断规则 interrupt中断操作必须在线程检测到线程中断之前执行

终结器规则 对象的构造函数必须在对象的终结器执行之前执行

传递性 操作顺序的传递性

2.发布

(1)不安全发布的本质 不安全发布操作的本质就是:对象的发布操作和对象的访问操作之间缺乏偏序关系(Happens-Before排序) 除了不可变对象外,使用被另外一个线程初始化的对象通常都是不安全的,除非对象的发布操作是在使用该对象的线程开始使用之前执行(即保存对象的发布操作在对象的加载操作之前也就是两个操作间保持偏序关系)

(2)安全发布的本质 安装发布对象的本质就是:使用锁或者volatile关键字来禁止操作之间的重排序,从而保持操作之间的偏序关系

(3)安全的初始化模式 初始化的几种模式: 初始化模式 优点 缺点 备注

synchronized加锁模式 禁止重排序,实现了线程安全的初始化

降低了初始化类或者创建实例的开销 数据竞争严重的情况下太耗性能

增加了访问被初始化延迟的字段的开销 不推荐使用

类初始化加锁模式 在类的静态初始化过程完成初始化,实现了线程安全的初始化

降低了初始化类或者创建实例的开销 仅适用于在构造时的状态,对于可变的对象读写操作之间仍然需要同步机制。仅限于静态字段的初始化

增加了访问被初始化延迟的字段的开销 类初始化期间获得一个锁,并且每个线程都至少获取一次这个锁以确保这个类已经加载。类初始化(静态初始化)时类在初始化阶段执行,在类型加载后被线程使用之前执行。

双重检测锁定模式(DCL) 降低了因synchronize锁带来的性能消耗

降低了初始化类或者创建实例的开销 没有实现线程安全的初始化 错误的不安全的延迟初始化方案

基于volatile改良后的双重检测锁定模式(VDCL) 降低了因synchronize锁带来的性能消耗,实现了线程安全的初始化

除了可用于静态字段也可以用于实例字段

降低了初始化类或者创建实例的开销 增加了访问被初始化延迟的字段的开销 无论通过类初始化加锁模式还是volatile关键字都是实现了禁止重排序或者实现操作间的偏序关系从而保证了操作内存的可见性。

3、初始化过程中的安全性

初始化安全性只能保证final修饰的值从构造过程完成时开始的可见性,对于非final的值,或者在构造完成后可以改变的值,必须采用同步来确保可见性

相关文章:

  • linux mysql 表名大小写_Linux系统下MySql表名大小写敏感问题
  • java 分支结构_Java分支结构
  • java里的文件显示繁体_关于在JSP页面上同时显示简体和繁体的问题(字符编码)...
  • java main.init_记录:java程序没有main函数只有init函数怎么运行,或者applet小程序怎么运行...
  • java配置一个json文件_Java 使用json 做配置文件
  • java 同时使用多个流_如何在带有lambda表达式的java 8中使用多个流...
  • 用java在JPanel中建一个表格_java常用面板(JPanel、JScrollPane)
  • map在Java集合_Java 集合 -- Map
  • jquery给日期赋值_jQuery 取值、赋值的基本方法整理
  • java 内部类定于_搞懂 JAVA 内部类
  • java二分法选相关择题_Java考试-2018年全国计算机二级考试精选习题及答案
  • java 表格类_Java动态表格类(DyTable)
  • mysql zhs16gbk_ASM磁盘组剔盘、加盘实施过程
  • java 实现动态验证码_java Servlet 实现动态验证码图片示例
  • Java多线程实现的四种方式_多线程实现的四种方式
  • #Java异常处理
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • Apache Pulsar 2.1 重磅发布
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • Gradle 5.0 正式版发布
  • HTTP请求重发
  • input的行数自动增减
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • JavaScript对象详解
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • 仿天猫超市收藏抛物线动画工具库
  • 工作中总结前端开发流程--vue项目
  • 详解NodeJs流之一
  • 新手搭建网站的主要流程
  • 硬币翻转问题,区间操作
  • 7行Python代码的人脸识别
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • ​软考-高级-信息系统项目管理师教程 第四版【第23章-组织通用管理-思维导图】​
  • #define 用法
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (蓝桥杯每日一题)love
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (十)T检验-第一部分
  • (已解决)vue+element-ui实现个人中心,仿照原神
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .NET Core 通过 Ef Core 操作 Mysql
  • .net 怎么循环得到数组里的值_关于js数组
  • /deep/和 >>>以及 ::v-deep 三者的区别
  • @RequestMapping用法详解
  • @serverendpoint注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • @SuppressLint(NewApi)和@TargetApi()的区别
  • [ C++ ] 继承
  • [ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(十)RCE (远程代码/命令执行漏洞)相关面试题
  • [ 隧道技术 ] cpolar 工具详解之将内网端口映射到公网
  • [Angular] 笔记 9:list/detail 页面以及@Output
  • [BZOJ]4817: [Sdoi2017]树点涂色