代码的有序性

44 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情

有序性

有序性概念

有序性(Ordering):是指程序中代码的执行顺序,Java在编译时和运行时会对代码进行优化(重排序)来加快速度,会导致程序终的执行顺序不一定就是我们编写代码时的顺序

instance = new SingletonDemo() 是被分成以下 3 步完成
 memory = allocate();     分配对象内存空间
 instance(memory);        初始化对象
 instance = memory;	   设置 instance 指向刚分配的内存地址,此时 instance != null

步骤2 和 步骤3 不存在数据依赖关系,重排与否的执行结果单线程中是一样的。这种指令重排是被 Java 允许的。当 3 在前时,instance 不为 null,但实际上初始化工作还没完成,会变成一个返回 null 的getInstance。这时候数据就出现了问题。

有序性演示

jcstress是java并发压测工具。wiki.openjdk.java.net/display/Cod… 修改pom文件,添加依赖 有如下代码 image.png

1、实际上上面两个方法会有很多线程来执行,为了讲解方便,我们只提出线程1和线程2来讲解。

2、I_Result 是一个保存int类型数据的对象,有一个属性 r1 用来保存结果,在多线程情况下可能出现几种结果?

情况1:线 程1先执行actor1,这时ready = false,所以进入else分支结果为1。

情况2:线程2执行到actor2,执行了num = 2;和ready = true,线程1执行,这回进入 if 分支,结果为 4。

情况3:线程2先执行actor2,只执行num = 2;但没来得及执行 ready = true,线程1执行,还是进入 else分支,结果为1。

情况4:0,发生了指令重排

image.png

pos_1处代码和pos_2处代码没有什么数据依赖关系,或者说没有因果关系。Java可能对其进行指令重排,排成下面的顺序。

image.png

此时如果线程2先执行到ready = true;还没来得及执行 num = 2; 。线程1执行,直接进入if分支,此时num默认值为0。 得到的结果也就是0。