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

为何ReentrantLock在Demo中失效而synchronized可正常运行?

问题分析与解决方案

看起来你在对比ReentrantLock和synchronized的过程中遇到了典型的锁使用错误,我来帮你拆解问题所在:

核心问题根源

你的断言失败和局部锁无效,本质是两个常见的ReentrantLock使用误区:

1. 类级锁时:锁的保护范围不完整 + 未用finally保证解锁

synchronized方法会自动把整个方法体纳入锁的保护范围,包括你的断言语句;但ReentrantLock是手动锁,如果你没把**所有共享变量操作(包括断言)**都放在锁的保护区间内,或者解锁语句没放在finally块中,就会出现问题:

  • 如果解锁语句在断言之前执行,那么解锁后其他线程可以立刻修改count,导致断言时count的值不再是1
  • 如果断言失败抛出AssertionError,且解锁语句没在finally里,会导致锁永久被持有,后续线程无法获取锁(或出现竞态条件)

2. 局部锁时:锁的作用范围完全失效

当你把ReentrantLock改成方法内局部变量时,每个线程调用方法都会创建一个全新的锁实例——不同线程的锁彼此独立,根本无法实现互斥访问。多个线程可以同时修改静态变量count,自然会出现count++后的值大于1的情况,触发断言错误。

正确的实现方式

要解决这个问题,你需要遵守ReentrantLock的三个使用原则:

  • 锁必须是多线程共享的实例(比如类级静态变量)
  • 所有对共享变量的操作(包括断言)必须放在锁的保护范围内
  • 用finally块确保锁一定会被释放,避免锁泄漏

下面是修正后的代码:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockZero {
    private static int count = 0;
    // 类级共享锁,确保所有线程使用同一个锁实例
    private static final ReentrantLock lock = new ReentrantLock();

    public synchronized int getCount() {
        count++;
        assert count == 1 : "Synchronized count mismatch: " + count;
        count--;
        return count;
    }

    public int getCountUsingLock() {
        lock.lock(); // 先获取锁
        try {
            // 所有对共享变量的操作都在锁保护下
            count++;
            assert count == 1 : "ReentrantLock count mismatch: " + count;
            count--;
            return count;
        } finally {
            lock.unlock(); // 无论是否异常,都确保释放锁
        }
    }

    public static void main(String[] args) {
        ExecutorService pool = Executors.newFixedThreadPool(2);
        ReentrantLockZero obj = new ReentrantLockZero();
        for (int i = 0; i < 1000; i++) {
            pool.submit(obj::getCount);
            pool.submit(obj::getCountUsingLock);
        }
        pool.shutdown();
    }
}

验证效果

启用-ea参数运行这段代码,两个方法都不会触发AssertionError:

  • finally块保证了锁的释放,不会出现锁泄漏
  • 锁的保护范围覆盖了所有count的操作和断言,确保了互斥访问
  • 类级锁保证了多线程共享同一个锁实例,实现了正确的同步

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:53:02