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

如何正确使用Java的synchronized关键字?线程累加计数异常排查

Java synchronized 同步失效问题分析与修复

你的代码中synchronized修饰实例方法run()的方式错误,导致线程未正确同步。

问题根源

synchronized修饰实例方法时,锁定的是当前实例对象。你创建了thr和thr2两个不同的Threadproblem实例,两个线程各自持有不同的锁,彼此的操作不会互相阻塞,因此静态变量counter的累加操作会出现线程安全问题,最终结果小于预期的200000。

修复方案

方案1:使用静态同步方法

将累加逻辑抽成静态同步方法,此时锁定的是Threadproblem类对象,所有线程共享同一把锁:

public class Threadproblem extends Thread {
    static long counter;

    synchronized public static void increment() {
        counter++;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100000; i++) {
            increment();
        }
    }

    public static void main(String[] args) {
        Threadproblem thr = new Threadproblem();
        Threadproblem thr2 = new Threadproblem();
        thr.start();
        thr2.start();
        try {
            thr.join();
            thr2.join();
        } catch (InterruptedException e) {
            System.out.println(e);
        }
        System.out.println("Counts:" + counter);
    }
}

方案2:锁定类对象的同步块

在run()方法中,直接对Threadproblem类对象加锁,确保所有线程共用同一锁:

public class Threadproblem extends Thread {
    static long counter;

    @Override
    public void run() {
        synchronized (Threadproblem.class) {
            for (int i = 0; i < 100000; i++) {
                counter++;
            }
        }
    }

    public static void main(String[] args) {
        Threadproblem thr = new Threadproblem();
        Threadproblem thr2 = new Threadproblem();
        thr.start();
        thr2.start();
        try {
            thr.join();
            thr2.join();
        } catch (InterruptedException e) {
            System.out.println(e);
        }
        System.out.println("Counts:" + counter);
    }
}

方案3:共用同一个Runnable实例

让多个线程共享同一个任务实例,此时synchronized修饰的实例方法会锁定这个共享的任务对象,实现同步:

public class Threadproblem implements Runnable {
    private long counter;

    @Override
    public synchronized void run() {
        for (int i = 0; i < 100000; i++) {
            counter++;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Threadproblem task = new Threadproblem();
        Thread thr = new Thread(task);
        Thread thr2 = new Thread(task);
        thr.start();
        thr2.start();
        thr.join();
        thr2.join();
        System.out.println("Counts:" + task.counter);
    }
}

补充说明

counter++是非原子操作,包含读取当前值、加1、写回新值三个步骤,即使没有循环,单个counter++也需要同步机制保证原子性,上述方案均已解决该问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 13:45:29