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

Java Socket并发写入问题:多线程连接下变量计数未达预期值

问题根源:竞态条件(Race Condition)

这是多线程环境下非常典型的共享资源同步问题!你的两个客户端线程在操作同一个全局变量时,读-改-写这三个步骤不是原子操作,导致了互相覆盖的情况:

比如线程A刚读到变量值为1,还没来得及把递增后的2写回去,线程B也读到了这个1,然后两个线程都把变量改成2并输出,相当于白白浪费了一次递增操作。这就是为什么服务器输出会是1 1 2 2 … 10 10,最终变量值只有10而不是预期的20。


解决方法

只要保证对共享变量的递增操作是原子性的(要么完整执行,要么不执行,中间不会被其他线程打断),就能解决这个问题,下面是两种常用的方案:

1. 使用synchronized同步锁

方案一:同步方法

如果你的递增逻辑是封装在一个方法里的,直接给方法加上synchronized关键字:

// 假设共享变量是静态全局变量
private static int count = 0;

// 同步的递增方法
public synchronized static void increment() {
    count++;
    System.out.print(count + " ");
}

每个线程调用这个方法时,必须先获取锁,同一时间只有一个线程能执行方法里的逻辑,从根本上避免了同时读写的冲突。

方案二:同步代码块

如果不想给整个方法加锁(比如方法里还有其他不需要同步的逻辑),可以只在操作共享变量的代码块上加锁:

// 用类对象作为锁(因为变量是静态的,属于类级别)
synchronized (YourServerClass.class) {
    count++;
    System.out.print(count + " ");
}

2. 使用原子类(更轻量级)

Java的java.util.concurrent.atomic包提供了一系列原子操作类,专门解决这种简单的共享变量原子操作问题,不需要手动加锁:

// 用AtomicInteger代替普通int
private static AtomicInteger count = new AtomicInteger(0);

// 在线程中调用原子递增方法
int newValue = count.incrementAndGet();
System.out.print(newValue + " ");

incrementAndGet()方法本身就是原子性的,底层通过CAS(Compare-And-Swap)机制实现,比synchronized的性能更好,适合这种简单的递增场景。


验证效果

用上面任意一种方案修改后,服务器的输出会变成1 2 3 4 … 19 20,最终变量值也会正确达到20,因为每一次递增操作都被完整执行,不会被其他线程打断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:27:14