Java并发编程实战 第16章 Java内存模型

 2019-12-10 15:44  阅读(849)
文章分类:Java Core

什么是内存模型

  • JMM(Java内存模型)规定了JVM必须遵循一组最小保证,这组保证规定了对变量的写入操作在何时将对其他线程可见。

  • JMM为程序中所有的操作定义了一个偏序关系,称为Happens-Before。两个操作缺乏Happens-Before关系,则Jvm会对它们进行任意的重排序。

    Happends-Before的规则包括:

    1. 程序顺序规则。若程序中操作A在操作B之前,则线程中操作A在操作B之前执行。
    2. 监视器锁规则。在同一监视器锁上的解锁操作必须在加锁操作之前执行。如图所示,
    3. volatile变量规则。对volatile变量的写操作必须在读操作之前执行。
    4. 线程启动规则。Thread.start必须在线程中执行的操作之前被调用。
    5. 线程关闭规则。线程中的任何操作必须在其他线程检测到该线程结束之前执行,或者从Thread.join中返回,或调用Threas.isAlive返回false。
    6. 中断规则。当一个线程在另一个线程上调用interrupt时,必须在被中断线程检测到interrupt调用之前执行。
    7. 终结器规则。对象的构造函数必须在启动该对象的终结器之前执行完成。
    8. 传递性。如果操作A在操作B之前执行,操作B在操作C之前执行,则操作A必须在操作C之前执行。

    双重检查加锁

  1. /**
  2. * 双重检查加锁, 不安全,
  3. * 线程可能看到无效的值, 可加上volatile修饰
  4. */
  5. public class DoubleCheckedLocking {
  6. private static Object resource;
  7. public static Object getInstance(){
  8. if (resource == null){
  9. synchronized (DoubleCheckedLocking.class){
  10. if (resource == null){
  11. resource = new Object();
  12. }
  13. }
  14. }
  15. return resource;
  16. }
  17. }

如果不使用volatile,可能看到对象的错误或者无效状态。

原因:因为JMM会在发布对象的引用和内部构造函数之间进行重排序,也就是说先把栈中对象的引用指向堆中的位置,但是由于重排序堆中的构造函数还没有执行完。但是使用volatile可以避免这种重排序。

因为接下来要看《Java并发编程的艺术》,里面有大量的章节讲述内存模型的只是,而这本书的这一章节比较晦涩,所以就不细看了。

点赞(0)
版权归原创作者所有,任何形式转载请联系作者; Java 技术驿站 >> Java并发编程实战 第16章 Java内存模型

相关推荐