java内存模型浅析

作者: Tifkingsly | 来源:发表于2018-08-19 22:00 被阅读0次

    前些日子写了一篇文章分析Java运行时内存区域,让我们对于Java内存有了基本的认识,很多人常常会把两者混淆。经过本篇文章的介绍,相信大家会更加熟悉和了解两者之间的区别。

    Java内存模型基础

    Java内存模型(JMM),从抽象的角度来看其定义了Java主内存与线程本地内存之间的抽象关系。在之前介绍多线程时有些过一篇关于volatile的文章,有提到主内存、线程本地内存,当时对于两者之间的关系并没有深入介绍,留到介绍内存模型时才来讲解。主内存(Main Memory)指的是所有线程可以共享的内存区域,本地内存(Local Memory)指的是线程本地私有的内存,其存储的是主内存中的一份副本。其实本地内存只是JMM的一个抽象,在物理上根本是不存在的。

    Java内存模型

    顺序一致性模型

    顺序一致性模型是一种理论化模型,其只是作为Java内存模型设计的一种参考。其主要包含两大特性:

    1、在一个线程中的所有操作,必须按照程序的顺序来执行;
    2、(不管程序是否同步)从每个线程的角度去看所有的操作都是有序的。在顺序一致性模型中所有的操作都具有原子性、而且其结果对所有线程可见。

    对于上述第1点,大家都比较好理解,对于单线程来说,我们希望程序执行顺序是有序的。对于第二点,多线程环境下的有序,大家或许会感到疑惑,因为多线程存在并发问题,下面来重点分析这一种情况。
    假设在一个程序中存在2个线程,线程A的执行顺序为:A1--->A2--->A3,线程B的执行顺序为:B1--->B2--->B3。若是线程同步的话,A、B线程的执行顺序为(假设A线程先执行):A1--->A2--->A3--->B1--->B2--->B3,符合上述第2点。若是A、B线程并不同步执行的话,情况则不一样了。假设其执行结果为下图:

    顺序一致性执行结果

    上图可以看出,无论是从线程A还是线程B的角度他们的执行顺序都没有发生变化,论证了上述第二个特性,所有的操作都是按照顺序执行。

    happens-before原则

    JSR-133内存模型使用happens-before原则来阐述程序执行过程与内存可见行。在JMM中,如果一个操作的执行结果对另外一个操作来说是可见的,那么这两个操作就必须要遵循happens-before规则。需要注意的是,happens-before描述的是操作结果的可见行,并不是操作的执行顺序下面介绍happens-before的具体规则:
    程序顺序规则:一个线程中的所有操作,happens-before于该线程中的任意后续操作;
    监视器锁规则:对于一个锁的解锁操作,happens-before于随后对其进行加锁的操作;
    volatile变量规则:对于一个volatile变量的写操作,happens-before于任意后续对这个变量的读操作;
    传递性规则:如果A操作 happens-before B操作,且B操作happens-before C操作,那么A操作 happens-before C操作;

    重排序介绍

    重排序是指编译器和处理器为了优化程序执行的性能而进行重新排序的一种手段。例如,a=1;b=2;这两个操作,就可能会被编译器或处理器进行重排序,改变其执行顺序。

    数据依赖性

    数据依赖性简单来说就是两个操作之间对于数据存在依赖,后面的操作依赖于前面的操作。例如,如果两个操作同时访问同一个变量,且其中一个操作为变量的写操作,那么这两个操作之间就存在数据依赖性。下面将举例说明:
    写后读: a=1;b=1;
    写后写: a=1;a=2;
    读后写: a=b;b=1;
    上述例子中的两个操作之间是存在数据依赖性的,因为只要改变两个操作执行的顺序那么其结果就会与预期不同。因此编译器与处理器在进行重排序时,必须要遵守数据依赖性。当然这里所说的数据依赖性仅仅针对的是单线程和单个处理器的情况,对于多个处理器和多线程之间的数据依赖性不会被编译器和处理器考虑。

    as-if-serial语义

    as-if-serial的语义是指不论编译器和处理器如何重排序,对于单线程来说,程序的执行结果都不能被改变。

    结束语

    写到这里相信大家对于Java内存模型会有一些了解,文章重点在于介绍Java内存模型中的一些理论知识。理解重排序,对于实际开发工作中关于多线程并发同步很有帮助的。对于多线程来说,编译器、处理器的优化不会考虑其数据依赖性,那么就可能改变预期执行结果,需要程序员自己通过同步手段进行控制。从我个人经验来看,对于这些知识的理解,能让自己从使用转向明白为什么的阶段。

    参考书籍:
    《Java并发编程艺术》
    《深入理解Java虚拟机》

    相关文章

      网友评论

        本文标题:java内存模型浅析

        本文链接:https://www.haomeiwen.com/subject/hoijeftx.html