Java 并发?重排序

重排序要具备数据依赖性:例如两个操作AB访问同一变量C,有一个是写操作,则两者存在依赖。

下面是依赖类型:有三种:

Java 并发?重排序

声明一下:

重要重排序中有以上给出的2个操作,程序执行结果就会变。

重排序只对单个处理器和线程有效。

as-if-serial单线程语句可以使重排序失效,也就是不具被依赖性。具有保护性,就像上面所描述的变量C,保护变量的位置关系不受AB干扰,执行结果就不会被改变。

以上ABC三者关系符合happens-before的程序顺序规则,AB两者的执行顺序不会改变执行结果,符合JMM。

以上操作在单线程不会影响结果,到了多线程则会。

正确使用同步串行执行操作能使程序执行顺序一致。

数据竞争:两个线程没有同步的读取同一个变量。

顺序一致性就算在不同步的情况下,线程的执行设计也应该要有规律顺序符合理念,可见性。JMM中则不保证此理念。

什么是总线事务:

Java 并发?重排序

总线的这些工作机制可以把所有处理器对内存的访问以串行化的方式来执行。在任意时间点,最多只能有一个处理器可以访问内存。这个特性确保了单个总线事务之中的内存读/写操作具有原子性。

在一些32位的处理器上,如果要求对64位数据的写操作具有原子性,会有比较大的开销。为了照顾这种处理器,Java语言规范鼓励但不强求JVM对64位的long型变量和double型变量的写操作具有原子性。当JVM在这种处理器上运行时,可能会把一个64位long/double型变量的写操作拆分为两个32位的写操作来执行。这两个32位的写操作可能会被分配到不同的总线事务中执行,此时对这个64位变量的写操作将不具有原子性。

当单个内存操作不具有原子性时,可能会产生严重的后果。