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

多线程学习问题:unlock方法中notify失效,等待线程无法唤醒

问题分析与修复方案

核心问题拆解

  • isOpen变量逻辑完全错误:这个static标记的设计逻辑混乱,隧道满时设为true,解锁时直接置为false,会导致等待线程无法正确判断当前隧道状态,甚至出现多个线程同时错误进入的情况。
  • AtomicInteger纯属冗余:既然已经用synchronized (this)保证了锁内操作的原子性,再用AtomicInteger完全没必要,反而增加了代码复杂度。
  • wait条件判断错误:等待的触发条件应该是隧道内车辆数达到上限,而非依赖全局isOpen标记;而且wait必须放在while循环中(这是多线程编程的硬性规范,防止虚假唤醒)。
  • 通知逻辑不严谨:notify()只会唤醒一个等待线程,但当隧道有空位时,可能有多个线程在等,只用notify可能导致部分线程永远无法被唤醒。

修复后的代码

public class Tunnel {
    // 用普通int即可,synchronized已保证原子性
    private int currentCars = 0;
    // 把最大容量抽成常量,便于维护
    private static final int MAX_TUNNEL_CARS = 3;

    void goIntoTunnel() throws InterruptedException {
        acquirePermission();
        try {
            int stayTime = (int) (Math.random() * 5000);
            System.out.println(Thread.currentThread().getName() + " 进入隧道");
            Thread.sleep(stayTime);
        } finally {
            // 必须用finally确保释放权限,避免异常导致死锁
            releasePermission();
        }
        System.out.println(Thread.currentThread().getName() + " 离开隧道,停留时间: " + stayTime);
    }

    void acquirePermission() throws InterruptedException {
        synchronized (this) {
            // 循环检查:只要隧道满就等待
            while (currentCars >= MAX_TUNNEL_CARS) {
                wait();
            }
            // 条件满足,进入隧道,计数加1
            currentCars++;
        }
    }

    void releasePermission() {
        synchronized (this) {
            // 离开隧道,计数减1
            currentCars--;
            // 唤醒所有等待线程,让它们重新检查准入条件
            notifyAll();
        }
    }
}

关键修复说明

  1. 移除冗余的AtomicInteger:在synchronized块内,普通int的读写操作是原子的,完全可以替代AtomicInteger,代码更简洁。
  2. 修正等待触发逻辑:直接用currentCars >= MAX_TUNNEL_CARS作为wait的判断条件,放在while循环中,确保线程被唤醒后重新检查状态,彻底避免虚假唤醒的问题。
  3. 替换notify为notifyAll:当有线程离开隧道时,唤醒所有等待线程,让它们竞争进入隧道(只用notify可能导致部分线程一直处于等待状态)。
  4. 用finally保证解锁:在进入隧道后的业务逻辑外层加finally块,确保无论是否抛出异常,都能释放隧道权限,避免死锁。
  5. 移除错误的isOpen变量:直接用当前隧道内车辆数作为准入判断的唯一依据,逻辑清晰且可靠。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:55:34