顺序一致性

当程序未正确同步时,就可能会存在数据竞争

Java内存模型规范对数据竞争的定义如下

  1. 在一个线程中写一个变量
  2. 在另一个线程中读同一个变量
  3. 写和读操作没有通过同步来排序

JMM对正确同步的多线程程序的内存一致性做了如下保证. 如果程序是正确同步的,程序的执行将具有顺序一致性(Sequentially Consistent)——即程 序的执行结果与该程序在顺序一致性内存模型中的执行结果相同. 这里的同步是指广义上的同步,包括对常用同步原语 (synchronized、volatile和final)的正确使用

顺序一致性内存模型

顺序一致性内存模型是一个被计算机科学家理想化了的理论参考模型. 顺序一致性内存模型有两大特性

  • 一个线程中的所有操作必须按照程序的顺序来执行
  • (不管程序是否同步)所有线程都只能看到一个单一的操作执行顺序. 在顺序一致性内存模型中,每个操作都必须原子执行且立刻对所有线程可见

未同步程序在JMM中不但整体的执行顺序是无序的,而且所有线程看到的操作执行顺序也可能不一致. 比如,在当前线程把写过的数据缓存在本地 内存中,在没有刷新到主内存之前,这个写操作仅对当前线程可见;从其他线程的角度来观察,会认为这个写操作根本没有被当前线程执行。只有当前线程把本地内存中写过的数据刷 新到主内存之后,这个写操作才能对其他线程可见。在这种情况下,当前线程和其他线程看到 的操作执行顺序将不一致

在JMM中,临界区内的代码 可以重排序(但JMM不允许临界区内的代码“逸出”到临界区之外,那样会破坏监视器的语 义)。JMM会在退出临界区和进入临界区这两个关键时间点做一些特别处理,使得线程在这两 个时间点具有与顺序一致性模型相同的内存视图

未同步程序的执行特性

对于未同步或未正确同步的多线程程序,JMM只提供最小安全性:线程执行时读取到的值,要么是之前某个线程写入的值,要么是默认值(0,Null,False). 为了实现最小安全性,JVM在堆上分配对象 时,首先会对内存空间进行清零,然后才会在上面分配对象(JVM内部会同步这两个操作)。因此,在已清零的内存空间(Pre-zeroed Memory)分配对象时,域的默认初始化已经完成了

文章链接 https://fangzongzhou.github.io/2020/10/16/计算机/技术栈/Java/并发编程/顺序一致性/