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

Java线程共享变量问题:程序输出不符预期,求解决方案

解决线程竞态条件导致的输出异常问题

看起来你遇到了典型的线程竞态条件问题,这是多线程环境下共享资源未被正确同步时的常见bug。结合你的代码片段和输出表现,我来帮你分析和解决:

问题根源

从你的输出(重复输出1-6,最终只到1000而非预期的2000)来看,你的Race_Condition2线程类应该是多个线程共享了同一个计数器变量,并且对这个变量的读写操作没有任何同步保护。

举个实际场景:假设你的Race_Condition类里有一个普通计数器count,两个线程同时执行“读取计数器→输出→递增”的逻辑。由于count++不是原子操作(它拆分为读取、递增、写入三个独立步骤),很可能出现这种情况:线程A刚读取到count=6,还没来得及递增写入,线程B也读取到了count=6,最终两个线程都会输出6,然后各自把计数器改成7,就出现了重复输出的情况。同时因为没有同步控制,两个线程的操作互相干扰,最终计数器只递增到1000就停止了。

解决方案

你需要对共享资源的访问进行同步控制,确保同一时间只有一个线程能操作计数器。这里提供两种常见的可靠解决方法:

方法1:使用synchronized同步机制

修改你的Race_Condition类,把操作计数器的逻辑封装成同步方法,或者在操作代码块上加锁,保证同一时间只有一个线程能执行该逻辑:

// 共享计数器类
public class Race_Condition {
    private int count = 1;
    private final int MAX = 2000;

    // 同步方法,确保同一时间仅一个线程能执行
    public synchronized void printNext() {
        if (count <= MAX) {
            System.out.print(count + " ");
            count++;
        }
    }

    // 供线程判断是否继续执行的同步方法(避免竞态)
    public synchronized boolean hasNext() {
        return count <= MAX;
    }
}

// 线程类:接收共享的计数器实例
public class Race_Condition2 extends Thread {
    private Race_Condition sharedCounter;

    public Race_Condition2(Race_Condition counter) {
        this.sharedCounter = counter;
    }

    @Override
    public void run() {
        while (sharedCounter.hasNext()) {
            sharedCounter.printNext();
        }
    }
}

// 主类:创建一个共享计数器,传给两个线程
public class Race_ConditonTest {
    public static void main(String[] args) {
        Race_Condition counter = new Race_Condition();
        Race_Condition2 R1 = new Race_Condition2(counter);
        Race_Condition2 R2 = new Race_Condition2(counter);
        R1.start();
        R2.start();
    }
}

方法2:使用AtomicInteger原子类

Java的java.util.concurrent.atomic包提供了原子操作类,它们的核心操作是原子性的,不需要手动加锁,适合简单计数器场景:

import java.util.concurrent.atomic.AtomicInteger;

// 共享计数器类
public class Race_Condition {
    private AtomicInteger count = new AtomicInteger(1);
    private final int MAX = 2000;

    public void printNext() {
        int current = count.getAndIncrement(); // 原子性的获取并递增
        if (current <= MAX) {
            System.out.print(current + " ");
        }
    }

    public boolean hasNext() {
        return count.get() <= MAX;
    }
}

这种方式底层通过CAS(比较并交换)机制实现原子操作,比手动加锁更简洁,性能也更优。

额外注意事项

  • 确保线程共享同一个计数器实例:如果你的Race_Condition2类里是每个线程自己new一个Race_Condition,那两个线程会各自输出1-1000,同样会出现重复输出且达不到2000的情况,所以一定要让所有线程使用同一个共享实例。
  • 终止条件要同步:判断线程是否继续执行的逻辑也要保证线程安全,避免因为竞态条件导致线程提前退出或无限循环。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:19:48