使用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
相关产品推荐
相关产品推荐

