美文网首页
Java synchronized 能防止指令重排序吗?

Java synchronized 能防止指令重排序吗?

作者: MuziBlogs | 来源:发表于2020-02-23 14:01 被阅读0次

一、synchronized 的有序性

 Java 里的操作无序现象是什么?

《深入理解 Java 虚拟机》- P374:

          如果在一个线程观察另一个线程,所有操作都是无序的指的是 “指令重排序” 和 “工作内存与主内存同步延迟” 现象。

指令重排是JVM层面对程序进行的优化措施,如果不深入了解,则在并发编程时可能会发生难以发现的Bug。

截止JDK1.8, Java 里只有 volatile 变量是能实现禁止指令重排的。

synchronized 虽不能禁止指令重排,但能保证有序性

这个有序性是相对语义来看的,线程与线程间,每一个 synchronized 块可以看成是一个原子操作,它保证每个时刻只有一个线程执行同步代码,它可以解决上面引述的工作内存和主内存同步延迟现象引发的无序

synchronized 和 volatile 的有序性与可见性是两个角度来看的:

    synchronized 是因为块与块之间看起来是原子操作,块与块之间有序可见

    volatile 是在底层通过内存屏障防止指令重排的,变量前后之间的指令与指令之间有序可见

synchronized 和 volatile 有序性不同也是因为其实现原理不同:

    synchronized 靠操作系统内核互斥锁实现的,相当于 JMM 中的 lock 和 unlock。退出代码块时一定会刷新变量回主内存

    volatile 靠插入内存屏障指令防止其后面的指令跑到它前面去了

总而言之就是, synchronized 块里的非原子操作依旧可能发生指令重排



二、volatile 的有序性

《Java 并发编程实战》 P287 指出,有 synchronized 无 volatile 会引发 DCL问题:

           线程可能看到引用的当前值,但对象的状态值确少失效的,这意味着线程可以看到对象处于无效或错误的状态

这意味着synchronized方法最后创建的对象能被其他线程访问到,但是可能会是无状态的,所以该对象虽存在但并不是一个可用的对象。

截图证明:

为何双重校验单例还要加上 volatile 的原因?

简单来讲,因为 new 这个指令是非原子操作,底层是分成几条指令来执行的,加上 volatile 是禁止指令重排,保证别的线程读到的时候一定是状态和引用正常的、一个完整的对象,防止其他线程看到的是对象还没有完全实例化的内容。

后记

值得一提的是 javap -v 编译出来的字节码指令还不是全部指令,它里面的 new 指令还是能更细分的,因为 volatile 的内存屏障指令还要深入到汇编的层次插入的。

关于synchronized我之前在看一本叫做《并发编程的艺术》和《深入理解Java虚拟机》这两本书,里面都是一些很浅显易懂的东西,该书透露着关于JVM和并发编程知道这些就够了的意思,但是在某种程度上,如果遇到类似双重校验为什么要加volatile这样的问题,还是需要一个合理的更底层的解释。

相关文章

  • Java synchronized 能防止指令重排序吗?

    一、synchronized 的有序性 Java 里的操作无序现象是什么? 《深入理解 Java 虚拟机》- P3...

  • Java指令重排序

    Java指令重排序Java内存模型允许编译器和处理器对指令重排序以提高运行性能,并且只会对不存在数据依赖性的指令重...

  • volatile 关键字

    volatile 关键字的作用:就是保证变量的可见性,防止指令重排序。 在 JDK1.2 之前,Java 的内存模...

  • volatile 关键字

    volatile 关键字的作用:就是保证变量的可见性,防止指令重排序。 在 JDK1.2 之前,Java 的内存模...

  • 单例模式

    内部静态类 双锁验证 防止指令重排序 枚举

  • Java volatile如何防止指令重排序

    voliate关键字的两个作用 1、 保证变量的可见性:当一个被volatile关键字修饰的变量被一个线程修改的时...

  • Java 线程同步

    1.Synchronized Java提供关键字synchronized来防止资源冲突。当任务要执行被synchr...

  • Concurrent

    JDK1.5前,JAVA使用synchronized实现对共享变量的同步,synchronized在字节码上加指令...

  • 单例模式

    懒汉式双重检查方式 这种方式是通过双重检查+synchronized实现线程安全。volatile:防止jvm指令...

  • 理解synchronized关键字

    一、synchronized关键字的含义 Java中的synchronized关键字的作用是为了防止资源冲突。当某...

网友评论

      本文标题:Java synchronized 能防止指令重排序吗?

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