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

使用ReentrantLock按4→3→2→1顺序执行多线程遇阻塞问题排查

线程按4→3→2→1顺序执行阻塞问题的修复方案

你的代码核心问题出在**threadId是实例变量**,所有线程共享同一个SequenceDemo实例,导致这个变量被多个线程覆盖。比如线程1启动后先把threadId设为1,紧接着线程4启动又把它改成4;当线程4执行完,currentThread减到3,但此时其他线程的threadId已经不是它们自己的id了(被后续启动的线程覆盖),所以即使被唤醒,currentThread.get() != threadId的条件依然成立,线程会继续等待,最终陷入阻塞。

修复方案

把threadId从实例变量改成局部变量,在循环判断时每次重新读取当前线程的名称并转换为int,确保每个线程判断的是自己的id,不会被其他线程干扰。

修复后的代码

public class SequenceDemo implements Runnable{
    
    static AtomicInteger currentThread = new AtomicInteger(4);
    ReentrantLock lock;
    Condition condition;
    
    public SequenceDemo(ReentrantLock lock, Condition condition) {
        this.lock = lock;
        this.condition = condition;
    }
    
    @Override
    public void run() {
        try {
            lock.lock();
            // 将threadId改为局部变量,每次循环都重新获取当前线程的id
            int threadId = Integer.parseInt(Thread.currentThread().getName());
            while(currentThread.get() != threadId) {
                condition.await();
            }
            
            System.out.println("Thread "+Thread.currentThread().getName()+" started executing");
            Thread.sleep(1000);
            System.out.println("Thread "+Thread.currentThread().getName()+" finished executing");
            
            currentThread.decrementAndGet();
            condition.signalAll();
            
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        
        SequenceDemo demo1 = new SequenceDemo(lock, condition);
        
        Thread t1 = new Thread(demo1, "1");
        Thread t2 = new Thread(demo1, "2");
        Thread t3 = new Thread(demo1, "3");
        Thread t4 = new Thread(demo1, "4");
        
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        
    }
}

修改点解释

  • 移除了实例变量threadId,改为在run()方法内定义局部变量,每次进入循环前重新获取当前线程的id,彻底避免多线程间的变量覆盖问题。
  • 线程被唤醒后,会重新读取自己的线程id与currentThread的值做比较,当currentThread递减到对应值时,线程就能正常执行。

测试输出

Thread 4 started executing
Thread 4 finished executing
Thread 3 started executing
Thread 3 finished executing
Thread 2 started executing
Thread 2 finished executing
Thread 1 started executing
Thread 1 finished executing

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 20:50:31