首页 > 代码库 > Java内存模型学习笔记

Java内存模型学习笔记

     Java内存模型(JMM):描述了java程序中各种变量(线程共享变量)的范根规则,以及在JVM中将变量存储到内存和从内存中读取出变量这样的底层细节。共享变量就是指一个线程中的变量在其他线程中也是可见的。

  共享变量可见性的实现:假设目前有两个线程:线程1和线程2。线程1的读取主内存的x=0到线程1的工作内存中,并执行将x=1操作;主内存会将x的最新值更新过来,即x=1;最后线程2的工作内存会将主内存的最新值更新过来。

  共享内存可见性的实现方式:synchronized实现和volatile实现

  1.synchronized实现:

  ①线程解锁前,必须把共享变量的最新值刷新到主内存中;

  ②线程加锁时,将清空工作内容中的共享变量的值,从而使用共享变量需要从主内从中重新读取最新的值(注意:加锁与解锁需要同一把锁)

  也就是说,线程解锁前对共享变量的修改,在下次加载时对其他线程也可见。线程执行互斥代码的过程如下:

  1??获得互斥??

  2??清空工作内存

  3??从主内存拷贝变量的最新值副本到工作内存

  ④执行代码

  5??将更新后的共享变量值刷新到主内存中

  6??释放互斥??

  PS:重排序 和 as-if-serial

  (1)重排序就是代码书写的顺序与实现执行的顺序不同。指令重排序是编译器或处理器为了提高程序性能而做的优化

  1??编译器优化重排序(编译器优化);

  2??指令级并行重排序(处理器优化);

  3??内存系统重排序(处理器优化)

  (2)as-if-serial就是无论如何重排序,程序执行代码的结果都和顺序执行的相同。

  在单线程中,重排序不影响内存的可见性。但是在多线程中,重排序可能会影响内存的可见性。具体如下:

  ①线程的交叉执行--------------------------------------------------------------------------------------原子性

  ②重排序结合线程的交叉执行--------------------------------------------------------------------------原子性

  ③共享变量更新后没及时在主内存更新-----------------------------------------------------------------可见性

  △synchronized解决方案:锁 + 原子性

  △volatile的解决方案:实现可见性,但是不能保证原子性。

  volatile的可见性实现:内存屏障和禁止重排序优化。

  1??对volatile变量执行写操作时,会在写操作后加入一条store屏障指令;

  2??对volatile变量执行读操作时,会在读操作后加入一条load屏障指令;

  volatile变量在每次被线程访问时,都强迫从主内存中重读该变量的值,而当该变量发生变化时,又会强迫线程将最新的值更新到主内存中,这样任何时刻,不同线程总能看到该变量的最新值。

 

Java内存模型学习笔记