`

【Java核心-进阶】Java内存模型——Happen-Before

    博客分类:
  • Java
 
阅读更多

简述

happen-before 简化的字面意思就是“某事件在另一事件之前发生”。

happen-before 关系是 Java 内存模型中保证多线程操作可见性的机制。

它可以保证语句的执行顺序,及对内存读写的操作顺序

为了提高效率,计算机中存在编译器指令重排和CPU乱序执行等优化方式;

这类优化方式在多线程场景中可能会导致多线程存取共享数据时数据状态不一致的问题。

线程内执行的每个操作都被保证在各自后续操作之前被执行——也就是程序会照着我们在编码时写定的先后顺序执行。

synchronized、volatile、lock 等相关代码的操作顺序都属于该机制的一部分。

 

 

为什么需要JMM(Java Memory Model)

CPU在执行程序时会将数据从内存读取到各自内核缓存中,且对该数据的修改可能只体现在该缓存中。

如果按照程序逻辑该数据是多线程共享的,那可能会导致其它CPU在使用该数据时得到的是旧值,而非之前那个CPU修改后的值。

 

早期的Java内存模型定义不够严谨,无法保证Java程序在各种硬件平台上行为的一致性。这导致Java程序在部分平台上运行时的效果与预期不符。

为了达到“书写一次,到处执行”的目标,Java自身需要有一套完善的内存模型,以屏蔽上述因不同硬件平台内存模型差异导致的程序行为不一致。

有了这么一套完善的内存模型,普通Java开发者、编译器及JVM开发者之间才能达成清晰的共识,相对简单地准确判断出什么样的多线程执行序列是符合规范的。

 

JVM开发者和编译器更关注于如何使用类似内存屏障(Memory-Barrier)之类的技术,来保证执行结果符合JMM的推断。

普通Java开发者更关注于volatile、synchronized等关键字的语义,并利用类似 happen-before 的规则,写出可靠的多线程程序

 

 

JMM是如何解决可见性等各种问题的

JMM 通常是利用内存屏障,通过禁止某些指令重排(包括编译器重排、处理器重排),来保证内存可见性。这也就是 happen-before 规则。

如,对于 volatile 变量,内存屏障机制会:

在“对该变量的写操作”之后,(编译器)加入一个“写屏障”;

在“对该变量的读操作”之前,(编译器)加入一个“读屏障”。

 

程序可以利用这些屏障,确保当前线程对共享变量的修改是对其它线程可见的。

可以近似理解为,在内存屏障下,当线程更改某共享数据后,屏障机制会强制将数据刷出处理器缓存,让其它线程拿到最新的值。

 

volatile变量的读写开销,比普通变量读取更高,比 synchronized 更低。

注:虽然 volatile 在某些场景中可以实现更低成本的多线程同步,但它并不能完全取代 synchronized。

分享到:
评论

相关推荐

    第29讲Java内存模型中的happen-before1

    7. **传递性**:如果 A `happen-before` B,B `happen-before` C,那么 A `happen-before` C。 理解 `happen-before` 规则对于编写高效的并发代码至关重要。例如,使用 `volatile` 变量可以确保多线程环境中的数据...

    深入浅出了解happens-before原则

    在 Java 内存模型(JMM)中,happens-before 原则是一个核心概念,它规定了多线程环境下的可见性原则。该原则的核心思想是:两个操作之间的 happens-before 关系,并不意味着前一个操作必须在后一个操作之前执行。...

    JSR133中文版,JSR133中文版

    Happen-Before内存模型是JSR-133中定义的一种内存模型,它描述了操作之间的顺序关系。这种内存模型可以用来确保在多线程环境下,操作的执行顺序是正确的。 JSR-133是Java语言中非常重要的规范,它定义了Java语言的...

    Java 高并发三:Java内存模型和线程安全详解

    例如,线程的启动操作Happen-Before该线程的任何读写操作,`synchronized`块的结束Happen-Before同一锁的下次获取,以及对`volatile`变量的写操作Happen-Before其他线程对这个变量的读操作。 线程安全是指在多线程...

    并发编程基础知识,java内存模型及多线程、volatile

    Happen-Before规则是一组用于保证线程之间执行顺序的规则,主要包括: - 程序顺序原则:在一个线程内部保证语义的串行性。 - volatile规则:volatile变量的写操作先于任何读操作。 - 锁规则:解锁操作必然发生在...

    volatile与happens-before的关系与内存一致性错误

    为了解决这类问题,引入了happens-before原则,这是Java内存模型(JMM)的一部分,它规定了一种特定的内存操作顺序,以确保正确同步。具体来说: 1. **线程操作的顺序**:在一个线程内,所有的操作都按照程序的顺序...

    Java并发编程--BlockingQueue.docx

    这得益于 Java 的 `happen-before` 规则。 JDK 提供的几种阻塞队列实现: 1. ArrayBlockingQueue:基于数组的有界阻塞队列,线程安全,遵循先进先出(FIFO)原则,可以通过构造函数设置容量。 2. ...

    make-fetch-happen:使获取发生在npm

    $ npm install --save make-fetch-happen 目录 fetch.defaults minipass-fetch选项 make-fetch-happen选项 opts.cacheManager opts.cache opts.proxy opts.noProxy opts.ca, opts.cert, opts.key opts....

    Java Service Wrapper64位破解

    去CSDN下载所谓破解出现以下错误:wrapper | Licensed to (null) for (null) wrapper | wrapper |... (6) jvm 1 | WrapperJNI Error: This can happen if the Wrapper binary is not... 自己改了之后可以部署了,分享包

    JAVA并发编程阿里巴巴.pptx

    - **Happen-Before规则**:确保代码执行的有序性,从而保证了数据的可见性。 - 程序顺序规则:代码按照程序顺序执行。 - 监视器锁定规则:对一个监视器的解锁一定发生在后续对同一监视器加锁之前。 - volatile...

    java并发编程实践的.pptx

    - **Happen-Before原则**:这是Java内存模型中的一个重要概念,它定义了不同线程之间操作的顺序关系。具体包括以下几种情况: - **程序次序法则**:如果一个操作在另一个操作之前发生,那么第一个操作的结果对第二...

    JVM面试题分享给需要的同学.zip

    6JVM内存模型的相关知识了解多少,比如重排序,内存屏障,happen-before,主内存,工作内存 7.简单说说你了解的类加载器,可以打破双亲委派么,怎么打破 8.说说你知道的几种主要的JVM参数 9.怎么打出线程栈信息 10....

    java并发编程常识

    在Java中,并发编程主要依赖于JVM的内存模型、线程安全、可见性、原子操作和内存管理等方面的知识。以下详细说明了在给定文件中提及的java并发编程的各个知识点: JVM内存模型 Java虚拟机(JVM)内存模型定义了Java...

    Java多线程中提到的原子性和可见性、有序性1

    此外,Java内存模型中有一个“先行发生”原则(Happen-Before),它定义了操作之间的顺序关系,确保操作B之前能看到操作A的影响。例如,线程A中的i = 1;在被线程B的j = i;看到之前,必须已经完成,这保证了线程B能够...

    阿里面试题 JVM-开源框架.docx

    - **happen-before原则**:定义了操作之间的内存可见性。 - **主内存与工作内存**:Java内存模型中的概念,线程有自己的工作内存,共享数据存放在主内存。 **类加载器**: - **双亲委派模型**:类加载请求首先交给...

    2021 java面试题.pdf

    内存屏障和happen-before原则是多线程编程中的概念,确保内存操作的顺序和可见性。GC Roots是垃圾收集的起点,用于确定对象是否可达。不同的垃圾收集器如CMS、G1和ZGC各有其优化策略,ZGC中的染色指针用于跟踪对象的...

    make-fetch-happen:加入失败者,我们正在提出要求!

    安装$ npm install --save make-fetch-happen 目录例子const fetch = require ( 'make-fetch-happen' ) . defaults ( { cacheManager : './my-cache' // path where cache will be written (and read)} )fetch ( '...

Global site tag (gtag.js) - Google Analytics