专栏首页用户4352451的专栏理解java中的happens-Before

理解java中的happens-Before

引言

Java的内存模型是主内存和工作内存,我们在进行程序调用的时候,变量值都是从主内存中读取然后复制一个副本,对这个副本进行操作。到最后将这个副本再更新到主内存中。但是这个只是针对于单线程,那如果是多线程呢?并且操作的是同一个变量值,那这两个线程之间的可见性应该如何来定义呢?

happens-Before

简介

  • java使用JMM模型后那就使用happens-before来阐述两个线程间的可见性
  • 在JMM中,如果一 个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系。这里提到的两个操作既可以是在一个线程之内,也可以是在不同线程之间。

规则

  • 程序顺序规则:一个线程中的每个操作,在前面的操作都happen-before他之后的操作。这也就是我们在一个方法中下面的变量总是可以拿到上面变量的值。
  • 监视器锁规则:对于一个锁的解锁,happens-before于对这个锁的加锁。监视器锁那就想想sychronized 当我们锁定某个对象的时候,解锁后那对于下一次来的线程会先知道这个锁是无锁状态,随后就加上锁。再理解一下就是监视器的加锁和解锁是线程间可见的。
  • volatile变量规则:对于volatile的写,对于后续的读都是happens-before的。volite的两个作用,防止指令重排和变量间线程可见。其中被修饰变量间线程可见,也就是我们在这里所说的线程间可见。
  • 有时候有人就会想volatile为什么能保证共享变量能线程间可见呢?其中有一种回答是,这个共享变量加了volatile关键字后后来的线程会先将工作内存中的数据先更新进主内存然后再去拿。仔细想想这是不是很牵强。要是有很多线程都共享这个变量了,那这难道把这些工作内存的变量都拉进到主内存更新,那主内存应该以哪个为准呢?解释不通呀。那我们使用这个happens-before变量规则来解释。就说他遵循happens-before规则。那这还是能说的过去的。那就又有人纠结了,那happens-before那又是咋回事呢?这他妈的是规范???

happens-before到底是什么?

  • 上面废话了那么多,我觉得我自己晕了。
  • 在强调一遍:java使用JMM模型后那就使用happen-before来阐述两个线程间的可见性
  • 那怎样就能是happens-before了?怎么就遵循happens-before,怎么就两个线程间可见了?
  • 线程间的可见,两种方式内存共享和消息传递。那我们如果说使用sychronized的锁对某个方法加锁,多个线程调用这个方法,那就可以说这几个线程间是happens-before的。
  • 还有就是一个成员变量被volatile 关键字修饰了,那有多个线程来修改这个变量,那这几个线程间也是有happens-before关系的。
  • 看一下下面的这张图来自(java并发编程艺术)我个人的理解是,遵循jMM定义的规则,且能保证线程间安全,这多个线程间就能使用happens-before对他们关系进行描述。

总结

  • 第三遍 java使用JMM模型后那就使用happens-before来阐述两个线程间的可见性
  • 写完感觉这东西也没什么。

参考

《java并发编程的艺术》

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 「每天一道面试题」如何理解Java中的happens-before?

    happens-before是Java内存模型中定义的两个操作之间的偏序关系,即如果操作A在操作B之前先发生,那么操作A产生的操作结果,操作B可以观察到,或者说...

    JavaQ
  • JMM 最最最核心的概念:Happens-before 原则

    关于 Happens-before,《Java 并发编程的艺术》书中是这样介绍的:

    飞天小牛肉
  • JAVA内存模型和Happens-Before规则

    上一篇文章王子给大家介绍了并发编程中比较关心的三个核心问题,可见性、有序性和原子性。

    HUC思梦
  • Java内存模型—JMMhappens-before规则

     有时候编译器、处理器的优化会导致runtime与我们设想的不一样,为此Java对编译器和处理器做了一些限制,JAVA内存模型(JMM)将这些抽象出来,这样编写...

    用户1174983
  • java内存模型

    java404
  • 【死磕Java并发】-----Java内存模型之happens-before

    在上篇博客(【死磕Java并发】—–深入分析volatile的实现原理)LZ提到过由于存在线程本地内存和主内存的原因,再加上重排序,会导致多线程环境下存在可见性...

    用户1655470
  • 【死磕Java并发】—–Java内存模型之happens-before

    在上篇博客(【死磕Java并发】—–深入分析volatile的实现原理)LZ提到过由于存在线程本地内存和主内存的原因,再加上重排序,会导致多线程环境下存在可见性...

    芋道源码
  • 【死磕Java并发】—–Java内存模型之happens-before

    在上篇博客(【死磕Java并发】—–深入分析volatile的实现原理)LZ提到过由于存在线程本地内存和主内存的原因,再加上重排序,会导致多线程环境下存在可见性...

    用户1655470
  • Java内存模型:看Java如何解决可见性和有序性问题

    你已经知道,导致可见性的原因是缓存,导致有序性的原因是编译优化,那解决可见性、有序性最直接的办法就是禁用缓存和编译优化,但是这样问题虽然解决了,我们程序的性能可...

    慕容千语
  • 并发编程进阶二:搞定可见性、有序性问题,用'它'就够了!!!

    承接上一篇"并发的三个潜在问题:CPU缓存引发的可见性、线程切换引发的原子性、编译优化引发的有序性"。

    浩说编程
  • Java 虚拟机 :Java内存模型

    这里我定义了两个共享变量 a 和 b,以及两个方法。第一个方法将局部变量 r2 赋值为 a,然后将共享变量 b 赋值为 1。第二个方法将局部变量 r1 赋值为 ...

    码农架构
  • 死磕 Java 并发 :Java 内存模型之 happens-before

    来源:chenssy, cmsblogs.com/?p=2102 那么我们正确使用同步、锁的情况下,线程A修改了变量a何时对线程B可见? 我们无法就所有场景...

    顶级程序员
  • 从另一个角度理解java并发

    掌握了Sequential Consistency一致性模型之后,我们重新审视一下java的并发。

    大神带我来搬砖
  • 高级面试:JAVA内存模型

    这里我定义了两个共享变量 a 和 b,以及两个方法。第一个方法将局部变量 r2 赋值为 a,然后将共享变量 b 赋值为 1。第二个方法将局部变量 r1 赋值为 ...

    Spark学习技巧
  • 并发学习笔记10-happens-before

    JMM把happens-before要求禁止的重排序分为下面两类: - 会改变程序执行结果的重排序; - 不会改变程序执行结果的重排序。

    WindCoder
  • 为什么会有重排序?

    上面一段代码是非常经典来讲CPU对指令重排序的案例。因为我们经过一段时间的Run出的结果很惊讶:

    chengcheng222e
  • 【并发编程】一文带你读懂深入理解Java内存模型(面试版本)

    主线如上图红色箭头,大家可以先看看整体讲的是什么。java内存模型前面是铺垫,后面是相关内容。

    java进阶架构师
  • 硬件内存模型到 Java 内存模型,这些硬核知识你知多少?

    Java 内存模型跟上一篇 JVM 内存结构很像,我经常会把他们搞混,但其实它们不是一回事,而且相差还很大的,希望你没它们搞混,特别是在面试的时候,搞混了的话就...

    Bug开发工程师
  • 硬件内存模型到 Java 内存模型,这些硬核知识你知多少?

    Java 内存模型跟上一篇 JVM 内存结构很像,我经常会把他们搞混,但其实它们不是一回事,而且相差还很大的,希望你没它们搞混,特别是在面试的时候,搞混了的话就...

    Java_老男孩

扫码关注云+社区

领取腾讯云代金券