Java内存模型对并发处理的三个特性

Posted 保护眼睛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java内存模型对并发处理的三个特性相关的知识,希望对你有一定的参考价值。

从上文的有关JMM的介绍、可以知道Java内存模型对并发的处理都围绕在三个特性—>原子性、可见性、有序性。

原子性

Java内存模型直接保证的原子性变量的操作包括read、load、assign、use、store、write.我们可以认为基本数据类型的访问、读写都是具有原子性的(除了long 和 double 的非原子的协定)。
如果一个场景需要的是更大范围的原子性的保证、JMM还提供了lock和unlock操作来满足这种需求、但是JVM并未将这种操作直接开放给用户,但是却提供了更高层次的字节码指令monitorenter和monitoreexit来隐式的使用这两个操作、对应到Java中的代码就是同步块synchronized关键字、也就是被synchronized修饰的代码区间内的操作具有原子性。

可见性

可见性指的是当一个线程修改了共享的变量的值的时候、其它的线程能够立即的得知这个修改。JMM是通过在变量修改之后将新值同步会主内存的、也就是在读取主内存的值之前刷新主内存的变量的值、依赖主内存作为传递的媒介来实现可见性的。无论是普通的变量还是被volatile变量都是这样的。普通的变量和volatile变量的区别就是:volatile特殊的规则保证了多线程操作时变量的可见性、普通的变量不能保证这一点。
当然、处理volatile关键字之外、Java中还有两个关键字可以实现可见性、分别是synchronized关键字和final关键字。synchronized关键字可见性的是“对一个变量unlock操作的时候、必需先把此变量同步到主内存中”这条规则实现的、final关键字实现可见性:被final关键字修饰的字段在构造器中一旦初始化完成的时候,并且构造器没有将“this”的引用传递出去在其它的线程中就能看见final的值。如下:变量i 和 j 都具备可见性、无需同步都能被其它的线程正确的访问。


    public static final int i;
    public final int j;

    static 
    {
        i = 0;
    }

    {
        j = 0;
    }

有序性

Java程序中的有序性可以总结为:如果在线程的内部观察的话、那么线程内部的操作都是有序的、如果在另外一个线程观察另一个线程的话、所有的操作都是无序的。前者指的是线程的内部表现为串行的语义、后者的意思是指令重排问题和工作内存和主内存之间同步的延迟。

java 语言提供了volatile 和sychronized两个关键字来保证线程之间操作的有序性。volatile 关键字本身就包含了禁止指令重排序的语义,而sychronized 则是由“一个变量在同一个时刻只允许一条线程对其进行lock操作”这条规则获得的,这条规则决定了持有同一个锁的两个同步块只能串行地进入。

以上是关于Java内存模型对并发处理的三个特性的主要内容,如果未能解决你的问题,请参考以下文章

学妹教你并发编程的三大特性:原子性可见性有序性

Java 并发学习总结

并发编程系列之什么是Java内存模型?

并发编程系列之什么是Java内存模型?

并发艺术--java内存模型

voliate怎么保证可见性