做网站不推广,网站建设学什么语言,微信支付需要网站备案,永济市网站建设一、前言在java多线程编程中#xff0c;volatile可以用来定义轻量级的共享变量#xff0c;它比synchronized的使用成本更低#xff0c;因为它不会引起线程上下文的切换和调度。所谓知己知彼、百战不殆。本文从JVM内存模型角度#xff0c;探讨volatile的实现原理。在明白了v…一、前言在java多线程编程中volatile可以用来定义轻量级的共享变量它比synchronized的使用成本更低因为它不会引起线程上下文的切换和调度。所谓知己知彼、百战不殆。本文从JVM内存模型角度探讨volatile的实现原理。在明白了volatile的实现原理后再回过头来使用它会有一种一览众山小的感觉吧使用起来会更加得心应手。二、Java内存模型(JMM)1、并发编程关键问题多线程编程涉及到两个关键问题线程之间的通信与同步。通信是指线程之间传递信息同步是指控制线程操作的执行顺序。通过共享内存或者消息通知这两种方法可以实现通信或同步。基于共享内存的线程通信是隐式的线程同步是显式的而基于消息通知的线程通信是显式的线程同步是隐式的。JAVA是前者即基于共享内存的隐式线程通信、显式线程同步。2、happens-before模型JMM呈现给程序员的模型是happens-before模型即顺序规则(单)线程中的写操作的结果happens before于于任意后续操作。锁规则 锁的解锁happens before于于锁的获取或加锁。volatile变量规则volatile写操作happens before于后续该变量的读操作是可见的。传递性A操作happens before于B操作B操作happens before于C操作则A操作happens before于C操作这儿的happens-before并不是指操作先于后续操作执行而是指操作结果对于后续结果是可见的。3、可见性在JMM中每个线程的内存由两层构成线程的“本地内存”、“主内存”。“本地内存”是JMM的一个抽象本身是不存在的它包括缓存、寄存器、写缓冲区、编译器及CPU的优化等。共享变量存放在“主内存”中“本地内存”中存放的是共享变量的副本。当线程中发生对共享变量的写操作时并不是直接写到“主内存”中的而是先写到“本地内存”的写缓冲区中只有当刷新(flush)到主内存后才可能被其它线程加载到其“本地内存”中此时我们说该共享变量是对其它线程“可见”的反之如果没有刷新(flush)到主内存就是对于其它线程“不可见”的。JMM就是通过控制主内存与每个线程的本地内存之间的交互来为Java程序员提供可见性的保证的三、volatile类型的内存语义happens-before规则提供了对volatile变量可见性的保证即volatile变量的写操作对后续任意对该变量的读操作是可见的。四、volatile类型的JMM实现再深入一些JMM是如何实现happens-before模型中的volatile规则的呢是通过限制这两种操作的重排序实现的。重排序规则第二个操作第一个操作volatile读volatile写普通读/写volatile读禁止重排序(1)禁止重排序(2)禁止重排序(3)volatile写禁止重排序(4)禁止重排序(5)-普通读/写-禁止重排序(6)-(1) 第一个操作是volatile读时不可以重排序否则读出来的结果可能是被修改过了的。(2)(5)(6)第二个是volatile写时所有操作都不可以被重排序于其后面因为要确保其写的结果对于后续操作可见。五、volatile类型使用的注意事项多个volatile操作或复合操作整体上不具有有序性适用于对volatile变量的写操作很少而读操作很多的环境