java

java并发-顺序一致性

3.3顺序一致性

顺序一致性内存模型是一个理论参考模型,在设计的时候,处理器的内存模型和编程语 言的内存模型都会以顺序一致性内存模型作为参照。

3.3.1 数据竞争与顺序一致性

JMM对正确同步的多线程程序的内存一致性做了如下保证。 如果程序是正确同步的,程序的执行将具有顺序一致性(Sequentially Consistent)——即程 序的执行结果与该程序在顺序一致性内存模型中的执行结果相同。马上我们就会看到,这对 于程序员来说是一个极强的保证。这里的同步是指广义上的同步,包括对常用同步原语 (synchronized、volatile和final)的正确使用。

3.3.2 顺序一致性内存模型

顺序一致性内存模型是一个被计算机科学家理想化了的理论参考模型,它为程序员提供 了极强的内存可见性保证。顺序一致性内存模型有两大特性。

  • 1)一个线程中的所有操作必须按照程序的顺序来执行。

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

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

3.3.3 同步程序的顺序一致性效果

class SynchronizedExample {
    int a = 0;
    boolean flag = false;
    public synchronized void writer() { //获取锁
        a = 1;
        flag = true;
    }                                                                         //释放锁
    public synchronized void reader() { //获取锁
        if (flag) {
            int i = a;
            ......
        }
    }                                                                        //释放锁
}

3.3.4 未同步程序的执行特性

未同步程序在JMM中的执行时,整体上是无序的,其执行结果无法预知。未同步程序在两 个模型中的执行特性有如下几个差异。

  • 1)顺序一致性模型保证单线程内的操作会按程序的顺序执行,而JMM不保证单线程内的 操作会按程序的顺序执行(比如上面正确同步的多线程程序在临界区内的重排序)。这一点前 面已经讲过了,这里就不再赘述。

  • 2)顺序一致性模型保证所有线程只能看到一致的操作执行顺序,而JMM不保证所有线程 能看到一致的操作执行顺序。这一点前面也已经讲过,这里就不再赘述。

  • 3)JMM不保证对64位的long型和double型变量的写操作具有原子性,而顺序一致性模型保 证对所有的内存读/写操作都具有原子性。

关于作者

程序员,软件工程师,java, golang, rust, c, python,vue, Springboot, mybatis, mysql,elasticsearch, docker, maven, gcc, linux, ubuntu, centos, axum,llm, paddlepaddle, onlyoffice,minio,银河麒麟,中科方德,rpm