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

Java多线程synchronized与Lock加锁不生效,静态变量自增结果随机是什么原因?

核心问题本质

所有锁机制生效的前提是多个线程竞争同一把共享锁,你的前两种写法都是每个线程持有独立的锁,完全没有互斥效果,自然无法保证静态共享变量count自增操作的原子性。

写法1(Lock版本)错误原因

你在test()方法内部每次执行时都会新建一个独立的ReentrantLock实例:

public void test() {
    Lock lock = new ReentrantLock(); // 每次调用test都会创建新锁
    // ...
}

1000个任务对应1000个完全独立的Lock实例,线程之间不会互相抢占锁,并发修改count时会出现值覆盖,最终结果小于等于1000。

正确的Lock写法需要将锁声明为类级静态共享变量,所有线程竞争同一把锁:

public class aaa implements Runnable {
    static int count = 0;
    // 全局唯一的共享锁
    static Lock lock = new ReentrantLock();
    // ...
    public void test() {
        try {
            lock.lock();
            count++;
            System.out.println(count);
        } finally {
            lock.unlock();
        }
    }
}

写法2(synchronized实例方法版本)错误原因

synchronized修饰实例方法时,锁对象是当前实例this。你提交任务时每次都新建aaa实例:

for (int i = 0; i < 1000; i++) {
    aaa thread = new aaa(); // 每次新建实例
    executor.execute(thread);
}

1000个任务对应1000个不同的aaa实例,每个线程锁的是自己的实例对象,互相之间没有互斥关系,还是会出现并发修改冲突。

锁aaa.class写法生效的原理

aaa.class是类对象,JVM中每个类只会有唯一的一个类对象,属于全局共享的锁对象,所有线程都要竞争这同一把锁,同一时间只会有一个线程执行同步块内的代码,既保证了count++的原子性,也保证了打印顺序的连续性,最终结果一定是1000。

总结

count是static修饰的类级共享变量,要保护它的并发安全,锁也必须是类级别的全局共享锁,不能使用每个实例独有的锁。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 06:06:02