JVM学习笔记——内存模型篇( 三 )

我们如果修改之前代码 , 就可以采用volatile修改:
package cn.itcast.jvm.t4.avo;public class Demo4_2 {static volatile boolean run = true;public static void main(String[] args) throws InterruptedException {Thread t = new Thread(()->{while(run){}});t.start();Thread.sleep(1000);run = false; // 线程t不会如预想的停下来}}内存模型之有序性我们将在下面仔细介绍有序性的特点
有序性介绍首先我们简单介绍一下有序性的定义:

  • 有序性就是指我们底层代码实现的具体顺序 , 在正常情况下是按正常顺序执行
有序性的注意点:
  • 同样底层也会进行部分优化 , 对于有序性的优化常常被称为指令重排 , 是指在不影响操作的前提下进行语句的优化调整
有序性问题我们同样给出一段代码:
int num = 0;boolean ready = false;// 线程1 执行此方法public void actor1(I_Result r) {if(ready) {r.r1 = num + num;} else {r.r1 = 1;}} // 线程2 执行此方法public void actor2(I_Result r) {num = 2;ready = true;}我们下面会给出其所有情况:
// 具体分为四种情况 , 前三种属于正常的多线程无锁导致的情况 // 情况1:线程1 先执行 , 这时 ready = false , 所以进入 else 分支结果为 1// 情况2:线程2 先执行 num = 2 , 但没来得及执行 ready = true , 线程1 执行 , 还是进入 else 分支 , 结果为1// 情况3:线程2 执行到 ready = true , 线程1 执行 , 这回进入 if 分支 , 结果为 4(因为 num 已经执行过了)// 但是第四种!却是因为代码重排所导致的情况:有序性分析首先我们在重新介绍一下指令重排:
  • JIT 编译器在运行时的一些优化 , 这个现象需要通过大量测试才能复现
我们可以给出结果为0的执行顺序:
线程2:ready = true;(由于操作更加简单 , 导致JIT将它放在前面编译)线程1:if判断 true线程1:r.r1 = num + num;(此时num为0) , 结果r1=0JVM 会在不影响正确性的前提下 , 可以调整语句的执行顺序:
// 下面是模拟情况:static int i;static int j;// 在某个线程内执行如下赋值操作// i为较为耗时的操作 , j为简单操作i = ...;j = ...;// 底层代码会认为i和j的赋值操作毫无关系 , 他们谁先执行都可以 , 所以会优先执行简单的操作// 所以我们的代码可能变为:static int i;static int j;j = ...;i = ...;有序性实现我们的可见性经常通过一种修饰词来实现:
  • volatile 修饰的变量 , 可以禁用指令重排
所以我们的代码经过修改后可以改造为以下代码:
int num = 0;boolean volatile ready = false;// 线程1 执行此方法public void actor1(I_Result r) {if(ready) {r.r1 = num + num;} else {r.r1 = 1;}} // 线程2 执行此方法public void actor2(I_Result r) {num = 2;ready = true;}happens-before我们在最后插入一个简单的内容happens-before:
  • 规定了哪些写操作对其它线程的读操作可见 , 它是可见性与有序性的一套规则总结
我们来简单介绍一些:
  1. 线程 start 前对变量的写 , 对该线程开始后对该变量的读可见
static int x;x = 10;new Thread(()->{ System.out.println(x);},"t2").start();
  1. 线程对 volatile 变量的写 , 对接下来其它线程对该变量的读可见
volatile static int x;new Thread(()->{ x = 10;},"t1").start();new Thread(()->{ System.out.println(x);},"t2").start();
  1. 线程解锁 m 之前对变量的写 , 对于接下来对 m 加锁的其它线程对该变量的读可见

    经验总结扩展阅读