java road

JVM-Java内存模型-学习笔记

2018-05-31  本文已影响66人  HardWJJ

1.内存模型的抽象

Java线程之间的通信由Java内存模型控制,JMM决定一个线程对共享变量的写入何时对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程以读/写共享变量的副本。

Java内存模型的抽象示意图如下:


11.png

2.重排序

为了提升性能,编译器和处理器会对指令进行重排序:
1.编译器优化重排序
2.指令级重排序
3.内存系统的重排序

3.处理器重排序与内存屏障指令

现代的处理器使用写缓冲区来临时保存向内存写入的数据。每个处理器上的写缓冲区,仅仅对它所在的处理器可见。这个特性会对内存操作的执行顺序产生重要的影响:处理器对内存的读/写操作的执行顺序,不一定与内存实际发生的读/写操作顺序一致!

4.volatile

  1. 由于volatile仅仅保证对单个volatile变量的读/写具有原子性,而监视器锁的互斥执行的特性可以确保对整个临界区代码的执行具有原子性。
  2. 可见性。对一个volatile变量的读,总是能看到(任意线程)对这个volatile变量最后的写入。
  3. 原子性:对任意单个volatile变量的读/写具有原子性,但复合操作不具有原子性(volatile++)。

5.锁

java并发编程中最重要的同步机制

``` class MonitorExample {//A执行writer()方法,随后线程B执行reader()方法
int a = 0;
public synchronized void writer() {  //1
    a++;                             //2
}                                    //3
public synchronized void reader() {  //4
    int i = a;                       //5
    ……
    }                                    //6
}

6.final

  • 在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,这两个操作之间不能重排序。
  • 初次读一个包含final域的对象的引用,与随后初次读这个final域,这两个操作之间不能重排序。
public class FinalReferenceEscapeExample {
final int i;
static FinalReferenceEscapeExample obj;

public FinalReferenceEscapeExample () {
    i = 1;                              //1写final域
    obj = this;                          //2 this引用在此“逸出”
      //1和2可能进行重排序,那么如果先拿到2可能final域还没构造完成,final域被初始化后的值
  }
}

7.参考资料

上一篇下一篇

猜你喜欢

热点阅读