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

Java类中线程同步无法实现问题求助

多线程同步失败的原因分析与解决方法

问题根源

你当前的两种同步尝试都没生效,核心原因是锁对象不唯一,每个线程都持有自己的锁,根本不会互斥:

  1. synchronized实例方法的问题:
    你给fori()加了synchronized修饰,但这是实例方法,锁的是当前SecondClass对象本身。你创建了5个SecondClass实例,每个线程对应一个实例,所以每个线程都拿着自己的锁,完全不会互相阻塞,同步自然无效。

  2. 实例锁对象的问题:
    你尝试用Object a = new Object();作为锁,但a是SecondClass的实例变量,每个SecondClass对象都会新建一个自己的a,结果还是每个线程用自己的锁,无法实现全局同步。

正确的解决方式

要实现多线程同步,必须让所有线程共用同一个锁对象,以下是几种可行方案:

方案1:使用类对象作为全局锁

修改fori()方法,用SecondClass.class作为锁对象,因为类对象在JVM中是全局唯一的:

private void fori() {
    try {
        synchronized (SecondClass.class) { // 所有线程共用同一个类锁
            for (int i = 0; i < 10000; i++) {
                plusFirstInt();
                plusSecondInt();
                plusThirdInt();
            }
        }
        Thread.sleep(10);
    } catch (InterruptedException exp) {
        System.out.println("Прервано!");
    }
}

方案2:将方法改为静态synchronized方法

静态synchronized方法的锁是类对象,同样能让所有线程共用同一个锁:

private static synchronized void fori() { // 静态同步方法,锁是SecondClass.class
    try {
        for (int i = 0; i < 10000; i++) {
            MainClass.firstInt++;
            MainClass.secondInt++;
            MainClass.thirdInt++;
        }
        Thread.sleep(10);
    } catch (InterruptedException exp) {
        System.out.println("Прервано!");
    }
}

注意:这种方式需要把方法里的逻辑直接写在静态方法中,静态方法不能直接调用实例方法。

方案3:定义全局静态锁对象

在MainClass中定义一个全局静态锁,让所有线程同步这个对象:

public class MainClass {
    static int firstInt;
    static int secondInt;
    static int thirdInt;
    public static final Object GLOBAL_LOCK = new Object(); // 全局锁对象
    // ... 其他代码不变
}

// 在SecondClass的fori()中使用这个锁:
private void fori() {
    try {
        synchronized (MainClass.GLOBAL_LOCK) {
            for (int i = 0; i < 10000; i++) {
                plusFirstInt();
                plusSecondInt();
                plusThirdInt();
            }
        }
        Thread.sleep(10);
    } catch (InterruptedException exp) {
        System.out.println("Прервано!");
    }
}

额外优化建议

另外,firstInt++这类操作本身不是原子性的(包含读-改-写三步),如果不想用同步块,也可以用AtomicInteger类替代普通int,更简洁地保证原子性:

import java.util.concurrent.atomic.AtomicInteger;

public class MainClass {
    static AtomicInteger firstInt = new AtomicInteger(0);
    static AtomicInteger secondInt = new AtomicInteger(0);
    static AtomicInteger thirdInt = new AtomicInteger(0);
    
    // 自增时调用incrementAndGet()
    private void plusFirstInt() {
        MainClass.firstInt.incrementAndGet();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 19:10:30