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

Java多线程修改变量未被其他线程感知问题排查求助

问题根因
  • OddEven实例未共享:你在main方法的线程创建循环里,每次迭代都new了新的OddEven对象,5个线程各持有一个独立的实例,实例内部的count、threadId都是线程私有的,完全不互通。T1修改的只是自己所持实例的threadId,其他线程的实例threadId永远是初始值1,所以T2判断自己名字不等于1就会一直等待。
  • threadId更新逻辑错误:你当前计算下一个threadId的逻辑是threadId = (threadId + 1)%noOfThreads,当noOfThreads为5时,计算结果的取值范围是04,而你创建的线程名字是15,当threadId被更新为0时,没有对应名字的线程能拿到执行权,所有线程都会陷入永久等待。
修复方案
  1. 将OddEven实例的创建移到线程创建循环外,让所有线程共享同一个实例
  2. 调整threadId的更新逻辑,让取值范围匹配线程名的1~5
修复后代码示例

Main类修改

public class Main {
    public static void main(String args[])
    {
        int noOfthreads = 5;
        Thread [] t = new Thread[noOfthreads];
        // 移到循环外,所有线程共享同一个实例
        OddEven oe = new OddEven(15, noOfthreads);
        for(int i = 0; i<noOfthreads ; i++) {
            t[i] = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        oe.printNumbers();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    };
                }
            });
        }
        for(int i = 0; i<noOfthreads ; i++) {
            t[i].setName(String.valueOf(i+1));
            t[i].start();
            System.out.println("started thread " + (i+1));
        }
        for(int i=0; i<noOfthreads; i++) {
            try {
                t[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

OddEven类修改

public class OddEven {
    int max ; 
    int count;
    Integer threadId; // 同步方法已保证可见性,可去掉volatile修饰
    int noOfThreads ;

    public OddEven(int max, int noOfThreads) {
        this.max = max;
        this.noOfThreads = noOfThreads;
        count = 1 ;
        threadId =1;
    }

    public synchronized void printNumbers() throws InterruptedException
    {
        while(count <= max)
        {
            while(!(Thread.currentThread().getName().equals(threadId.toString()))) 
            {
                wait();
            }
            System.out.println("thread " + Thread.currentThread().getName() + " printed " + count) ;
            count++;
            // 修复更新逻辑,取值范围匹配1~noOfThreads
            threadId = (threadId % noOfThreads) + 1;
            notifyAll();
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 13:24:06