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

Java多线程synchronized同步失效两线程输出相同num值原因咨询

并发异常原因

该异常的核心诱因是synchronized锁未实现全局互斥,加锁逻辑完全失效,具体逻辑如下:

  • 你定义的锁对象obj是sell_ticket类的实例成员变量,没有加static修饰。当你实例化s1、s2两个sell_ticket对象时,两个实例会各自生成独立的obj对象,两个线程持有的锁是完全无关的两个对象。
  • synchronized的互斥生效前提是:多个竞争访问共享资源的线程,必须争抢同一个锁对象,同一时间才会只有一个线程进入同步代码块。现在s1加锁用的是自身持有的obj,s2加锁用的是自身持有的obj,两个锁互不干扰,两个线程可以同时进入同步块操作共享的静态变量num,自然会出现同时读到num=0、重复打印0的问题。

修复方案

只需要保证所有线程访问共享变量num时,争抢的是同一个全局唯一锁即可,两种常用实现:

  1. 将锁对象改为类级别的静态成员,所有sell_ticket实例共用同一个锁对象
static int num = 0;
// 给obj添加static修饰,全类共享唯一实例
static Object obj = new Object();
@Override
public void run() {
    while(true){
        synchronized (obj){
            if(num < 10000){
                System.out.println("sell ticket " + this.getName() + " " + this.num);
                num ++;
            }
            else
                break;
        }
    }
}
  1. 直接使用类的Class对象作为锁,JVM加载类时生成的Class对象是全局唯一的
static int num = 0;
@Override
public void run() {
    while(true){
        // 锁使用当前类的Class对象
        synchronized (sell_ticket.class){
            if(num < 10000){
                System.out.println("sell ticket " + this.getName() + " " + this.num);
                num ++;
            }
            else
                break;
        }
    }
}

注意:你的代码中num是静态成员,属于类级别的共享资源,所有对该资源的读写操作都必须处于同一把锁的保护下,否则同步逻辑不会产生任何互斥效果。

内容的提问来源于stack exchange,提问作者吕泓瑾

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 03:09:16