栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java内存模型

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java内存模型

目录

内存模型(Java memory model)

JMM体现在以下几个方面

什么是happen-before

原子性

有序性

可见性

工作内存和主内存的概念

volatile(易变关键字)


内存模型(Java memory model)

简单的说,JMM 定义了一套在多线程读写共享数据时(成员变量、数组)时,对数据的可见性、有序性、和原子性的规则和保障。

JMM即Java Memory Model,它定义了主存、工作内存抽象概念,底层对应着CPU寄存器、缓存、硬件内存、CPU指令优化等。


JMM体现在以下几个方面


·原子性·保证指令不会受到线程上下文切换的影响
·可见性-保证指令不会受cpu缓存的影响
·有序性-保证指令不会受cpu指令并行优化的影响

什么是happen-before

JMM可以通过happens-before关系向程序员提供跨线程的内存可见性保证(如果A线程的写操作a与B线程的读操作b之间存在happens-before关系,尽管a操作和b操作在不同的线程中执行,但JMM向程序员保证a操作将对b操作可见)。

具体的定义为: 1)如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。

2)两个操作之间存在happens-before关系,并不意味着Java平台的具体实现必须要按照happens-before关系指定的顺序来执行。如果重排序之后的执行结果,与按happens-before关系来执行的结果一致,那么这种重排序并不非法(也就是说,JMM允许这种重排序)。

具体的规则:

(1)程序顺序规则:一个线程中的每个操作,happens-before于该线程中的任意后续操作。

(2)监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。

(3)volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。

(4)传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。 (5)start()规则:如果线程A执行操作ThreadB.start()(启动线程B),那么A线程的ThreadB.start()操作happens-before于线程B中的任意操作。

(6)Join()规则:如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。

(7)程序中断规则:对线程interrupted()方法的调用先行于被中断线程的代码检测到中断时间的发生。

(8)对象finalize规则:一个对象的初始化完成(构造函数执行结束)先行于发生它的finalize()方法的开始。

原子性

只能采用加锁的方式实现,或者本身这条命令就是原子命令,比如乐观锁中的compareAndSet。

有序性

指令有时候会受cpu指令并行优化的影响,所以有时候需要让指令按顺序执行。

例子,单例模式的双重校验锁写法:必须使用volatile修饰。

public class LazyMan {
    private LazyMan(){

    }

    private static volatile LazyMan lazyman;
    
    public static LazyMan getInstance(){

        if(lazyman==null){
            synchronized (LazyMan.class){
                if(lazyman==null){
                    lazyman =  new LazyMan();
                }
            }
        }
        // 正常顺序  分配内存  new 对象  指针指向堆区
        // 重排顺序  分配内存  指针指向堆区  new 对象
        // 当指针指向堆区的时候  如果有线程 来了 那么 lazyman!=null  直接返回对应的对象
        // 但是这个对象没有创建完毕 所以必须用 volatile修饰
        return lazyman;
    }

    
}

可见性

工作内存和主内存的概念

两个线程都有自己的工作内存,这个工作内存和主线程中的内存不一样。

volatile(易变关键字)

它可以用来修饰成员变量和静态成员变量,他可以避免线程从自己的工作缓存中查找变量的值,必须到主存中获取它的值,线程操作 volatile 变量都是直接操作主存。

volatile不能保证原子性,仅用在一个写线程,多个读线程的情况,多个线程写的时候也会有 错误只能保证看到最新值,不能解决指令交错.

注意 synchronized 语句块既可以保证代码块的原子性,也同时保证代码块内变量的可见性。但缺点是synchronized是属于重量级操作,性能相对更低。

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/953038.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号