并发问题的原因可以归结为三大类:可见性,有序性和原子性。

可见性的原因是CPU缓存,不同CPU之间缓存的数据互相之间不可见。
有序性的原因是编译优化(指令重排序)
原子性的原因是一条高级指令可能对应多个CPU指令,而OS只能保证CPU指令的原子性。

解决方案

解决可见性和有序性可以通过禁用CPU缓存和禁用编译优化实现,但这样会严重影响程序性能,合理的方案应该是按需禁用。Java内存模型规范了JVM如何提供按需禁用缓存和编译优化的方法,具体包括:volatile, synchronized和final关键字以及六项Happens-Before规则

volatile

这个关键字不是Java语言特有的,C语言中就已引入,最原始的意义就是禁用CPU缓存。如声明一个变量 volatile int a = 1; 表示告诉编译器,对这个变量的读写禁用CPU缓存,必须从内存读写。

Happens-Before规则

它的含义是:前面一个操作的结果对后续操作是可见的。Happens-Before规则约束了编译器的优化行为,虽允许编译优化,但要求编译器优化后一定遵守Happens-Before规则。

1. 程序的顺序性规则

这条规则指:同一个线程中,按照程序顺序,前面的操作happens-Before于后续的任意操作。比较容易理解,即程序前面对某个变量的修改一定是对后续操作可见的。

2. Volatile

对一个 volatile 变量的写操作相对于后续对这个 volatile 变量的读操作可见。即volatile变量直接从内存读写

3. 传递性

指如果 A Happens-Before B,且 B Happens-Before C,那么 A Happens-Before C。

4. 管程中锁的规则

指对一个锁的解锁happens-before于后续对这个锁的加锁。管程是一种通用的同步原语,在Java中就是synchronized。管程中的锁在Java中是隐式实现的,由编译器自动完成加解锁。

即一个线程在同步代码块中对变量的写对另一个进入代码块的线程可见。

5. 线程start()规则

指主线程A启动子线程B后,子线程B能够看到主线程在启动B之前的操作。

6. 线程join规则

指主线程A等待子线程B完成(主线程A中调用B线程的join()方法实现),当B完成后,主线程能够看到子线程的操作(共享变量的值可见)。

final关键字

在JDK 1.5 以后 Java 内存模型对 final 类型变量的重排进行了约束。现在只要我们提供正确构造函数没有“逸出”,就不会出问题。

小结

Java的内存模型是并发编程领域的一次重要创新,其中happens-before规则比较难懂一些。Happens-before本质是上解决可见性的问题。如果A happens-before B, 即使A在线程1中发生,那么在线程2中也能看到A发生的事情。

1. Java并发编程-Java内存模型相关推荐

  1. java并发编程系列-内存模型基础

    java线程之间的通信对程序开发人员是完全透明的,内存的可见性问题很容易困扰很多开发人员.本篇博文将揭开java内存模型的神秘面纱,来看看内存模型到底是怎样的. 并发编程中需要处理的两个关键问题: · ...

  2. Java并发编程-Java内存模型(JMM)

    前言 在上一章 Java并发编程-Android的UI框架为什么是单线程的? 中笔者介绍了并发编程线程安全「三大恶」:「可见性」.「原子性」以及「有序性」 广义上来说,并发编程问题笔者归纳为:是由于后 ...

  3. java 并发存储,java并发编程——Java存储模型(JMM)

    --仅作笔记使用,内容多摘自<java并发编程实战> Java内存模型(JMM) JMM是Java并发编程的基础,了解JMM,可以帮助我们对并发编程的机制有更深入的了解,在了解JMM之前, ...

  4. java并发编程-volatile内存实现和原理

    2019独角兽企业重金招聘Python工程师标准>>> 前面的博文说了java的内存模型,介绍了java内存模型的基础,此篇文章来说一下volatile关键字,这个在并发编程中,占有 ...

  5. java并发编程(7) 共享模型之工具 - stampedLock、semaphore、CountdownLatch、CyclicBarri

    文章目录 前言 1. stampedLock 1. 概述 2. 代码 1. 读读 2. 读写 3. 注意 2. Semaphore 1. 基本使用 2. 应用场景 3. 原理 3. Countdown ...

  6. java 并发模型总类_java并发编程系列-内存模型基础

    java线程之间的通信对程序开发人员是完全透明的,内存的可见性问题很容易困扰很多开发人员.本篇博文将揭开java内存模型的神秘面纱,来看看内存模型到底是怎样的. 并发编程模型的分类 并发编程中需要处理 ...

  7. Java并发篇_Java内存模型

    在并发编程中,我们通常会遇到以下三个问题:原子性问题,可见性问题,有序性问题.那么它们产生的原因和在Java中解决的办法又是什么呢? 一.内存模型的相关概念 ​ 计算机在执行程序时,每条指令都是在CP ...

  8. java float内存结构_Java后端开发岗必备技能:Java并发中的内存模型

    欢迎关注专栏: Java架构技术进阶 .里面有大量batj面试题集锦,还有各种技术分享,如有好文章也欢迎投稿哦. JMM通过构建一个统一的内存模型来屏蔽掉不同硬件平台和不同操作系统之间的差异,让Jav ...

  9. Java并发编程实战~Actor 模型

    Hello Actor 模型 Actor 模型本质上是一种计算模型,基本的计算单元称为 Actor,换言之,在 Actor 模型中,所有的计算都是在 Actor 中执行的.在面向对象编程里面,一切都是 ...

最新文章

  1. 小时候糖吃多了,长大后记性会变差| Nature子刊最新研究
  2. 理解 RXSwift:单元测试(四)
  3. 区块链学堂(4):以太坊基本概念及工具Geth、Browser-solidity、Mist
  4. flutter 开关Switch与复选框Checkbox
  5. 在asp.net2.0中使用存储过程
  6. 炒股要学会向动物学习
  7. MySQL-第二篇SQL语句基础(1)语句分类及DDL语句
  8. python的if和else、for、while语法_Python中的if、while、for 语法及实例
  9. ddr4单颗粒最大_国产内存来了:长鑫发布DDR4/LPDDR4X内存
  10. Python绘图 好用的网址
  11. selenium+java+chrome环境搭建
  12. html点击某部分后弹出展开,点击按钮弹出框并显示内容
  13. Excel通过图片名插入图片
  14. dojo 框架实战笔记
  15. fullPage的简单使用
  16. 入手评测 联想小新PRO14,华硕灵耀14s和联想YOGA14s选哪个
  17. 能力值的计算:一年 365 天,以第 1 天的能力值为基数,记为 1.0,当每天好好学习时能力值相比前一天提高 1‰,当没有学习时由于遗忘等原因能力值相比前一天下降 1‰
  18. chart.js画图
  19. 计算机毕业设计之二手书交易系统
  20. 2020年有哪些ERP系统软件

热门文章

  1. 微信会员卡系统如何助力服装店提升业绩(下)
  2. pcie转sata3硬盘不启动_【聚评测】第2期 名单公示【阿卡西斯 NVMe M.2 固态硬盘盒】...
  3. FFmpeg: 通过ffplay给视频加字幕
  4. 欧特克加入制裁,科技真的无国界吗?
  5. 什么是一方库、二方库、三方库
  6. 【SpringBoot】SpringBoot+Zookeeper+Dubbo整合
  7. 湛江各县市区5G建设计划已明确,共计7460座5G基站
  8. 4类程序员直呼好用的嵌入式开发辅助工具
  9. 杭州python培训价格
  10. 怎么将PDF图纸转换成CAD图纸