You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Peterson解法中线程共享静态变量不更新?添加空输出却正常

Peterson算法中共享变量无法更新的原因分析

我在尝试用Peterson解法解决临界区问题时,发现共享静态变量无法在线程中正确更新,除非在循环里加上空的System.out.print("");语句。请问这一现象的原因是什么?

附Peterson.java代码如下:

public class Peterson {
    public static void main(String[] args) throws InterruptedException {
        Process p1 = new Process(0);
        Process p2 = new Process(1);
        p1.start();
        p2.start();
        p1.join();
        p2.join();
    }
}

class Process extends Thread {
    static int turn;
    static boolean[] wait = new boolean[2];

    int ind;
    public Process(int ind) {
        this.ind = ind;
    }

    @Override
    public void run() {
        int ind2 = 1-ind;
        wait[ind] = true;
        turn = ind2;
        
        // USING THIS WORKS
        // while(wait[ind2] && turn == ind2) {System.out.print("");}
        // USING THIS DOESN'T WORK
        while(wait[ind2] && turn == ind2) {;}

        // Critical Section
        System.out.printf("%d Started%n", ind);
        for (long t = System.currentTimeMillis(); System.currentTimeMillis() - t < 100;);
        System.out.printf("%d Ended%n", ind);

        wait[ind] = false;
    }
}

原因分析

1. Java内存模型的可见性缺失

Java的内存模型中,每个线程都拥有独立的工作内存,共享变量存储在主内存中。线程读取共享变量时会先将其拷贝到工作内存,修改后再写回主内存。但如果没有同步机制约束,JVM会进行优化:比如将共享变量缓存到工作内存,不及时从主内存刷新最新值,也不把本地修改同步回主内存。

你的代码里turn和wait都是共享静态变量,但空while循环没有任何同步操作,JVM会认为这些变量的值不会被其他线程修改,直接缓存到当前线程的工作内存中,导致线程无法感知另一个线程对这些变量的修改,从而一直卡在循环里无法退出。

2. System.out.print的同步副作用

System.out是PrintStream的实例,它的print方法内部用synchronized关键字实现了同步。当执行同步代码时,Java会触发内存屏障:

  • 进入同步块前,线程会失效工作内存中的变量,强制从主内存读取最新值
  • 退出同步块后,线程会将工作内存中的修改写回主内存,确保其他线程可见

哪怕是空的System.out.print("");,也会触发这个同步机制,让线程能正确读取到另一个线程修改后的wait和turn变量,从而退出循环。

3. 正确的解决方案

不要依赖System.out这种临时的hack方式,应该用Java原生的并发机制保证可见性:将共享变量声明为volatile,修改后的代码如下:

class Process extends Thread {
    static volatile int turn;
    static volatile boolean[] wait = new boolean[2];

    // 其余代码不变
}

volatile关键字会强制线程每次读取变量都从主内存获取,修改后立即写回主内存,既保证了变量的可见性,又禁止了指令重排序,完全符合Peterson算法的内存语义要求。

内容的提问来源于stack exchange,提问作者John

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 16:13:18