并发编程-Java内存模型:解决可见性与有序性问题

Posted hello---word

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并发编程-Java内存模型:解决可见性与有序性问题相关的知识,希望对你有一定的参考价值。

背景

我们知道导致cpu缓存导致了可见性问题,编译器优化带来了有序性问题。那么如果我们禁用了cpu缓存与编译器优化,就能够解决问题,但是性能就无法提升了。所以一个合理的方案,就是按照一定规范来禁用缓存和编译器优化,即在某些情况下禁用缓存与编译器优化。Java内存模型就是这样的一个规范,用来解决可见性与有序性问题

概念

java内存模型本质上就是规范了JVM如何按照规则禁用缓存和编译器优化,既面向应用开发人员,也面向jvm的实现。这些规范包括了volatile、synchronized和final三个关键字,以及六项Happens-Before规则。

volatile

volatile实质就是告诉编译器,对volatile修饰的变量,不能使用cpu缓存,必须从内存中读取或者写入。

Happens-Before规则,简称为HB

HB本质是一种可见性,即前面一个操作结果对后面的操作是可见的,换句话说就是后面的操作能够看见前面的操作结果。HB约束了编译器的优化行为,允许优化,但是优化后的结果要符合HB规则

同一线程顺序性规则

这条规则是指在一个线程中,按照程序顺序,前面的操作HB于后续的操作。

volatile变量规则

这条规则是指对一个 volatile 变量的写操作, HB于后续对这个变量的读操作。

传递性

这条规则是指A HB于 B,B HB于 C,那么A HB 于C。
根据以上三条格则继续看下面的例子

public class HappensBeforeDemo 
    int x = 0;
    volatile boolean v = false;
    public void write()
        x = 42;
        v = true;
    
    public void read()
        if(v)
            //x为多少呢
        
    

当线程A执行完write方法,线程B执行read方法后,读到了v为true后,x是多少呢?首先在线程A中,根据同一线程顺序性规则,x=42 HB与v=true;再根据volatile变量规则,v=true的写操作HB于v的读操作;再根据传递性规则,x=42 HB于v的读操作,所以线程B中的值一定为42。在java并发包中的工具类,正是依靠这三条规则来实现可见性的

synchronized锁规则

这条规则指对一个锁的解锁操作HB于后续对这个锁的加锁加锁操作

线程start()规则

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

线程join规则

在主线程A中等待子线程B完成(主线程A通过调用子线程B的join方法实现),当子线程完成后(主线程中的join方法返回),主线程能够看到子线程的操作结果

以上是关于并发编程-Java内存模型:解决可见性与有序性问题的主要内容,如果未能解决你的问题,请参考以下文章

并发编程——可见性与有序性

Java并发基础Java内存模型解决有序性和可见性

原创Java并发编程系列04 | Java内存模型详解

voliate怎么保证可见性

并发编程(学习笔记-共享模型之内存)-part4

重点知识学习(8.2)--[JMM(Java内存模型),并发编程的可见性原子性有序性,volatile 关键字,保持原子性,CAS思想]