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

Java双线程交替输出12问题:Semaphore与Mutex实现方案排查

错误排查

原代码的核心问题是创建了两个独立的SemTest实例:线程1操作的是semTest1的信号量,线程2操作的是semTest2的信号量,两者的sem1、sem2完全不共享。线程2尝试获取的是自己实例中初始许可为0的sem2,永远无法获取到许可,因此输出第一个1后就陷入阻塞。

Semaphore正确实现方案

使用同一个实例让两个线程共享同一组信号量,保证线程间的同步交互:

import java.util.concurrent.Semaphore;

public class SemaphoreAlternate {
    // 线程1的许可初始为1,线程2的许可初始为0
    private final Semaphore sem1 = new Semaphore(1);
    private final Semaphore sem2 = new Semaphore(0);

    public static void main(String[] args) {
        SemaphoreAlternate instance = new SemaphoreAlternate();

        // 线程1:输出1
        new Thread(() -> {
            while (true) {
                try {
                    sem1.acquire();
                    System.out.print("1");
                    sem2.release(); // 释放许可让线程2执行
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }).start();

        // 线程2:输出2
        new Thread(() -> {
            while (true) {
                try {
                    sem2.acquire();
                    System.out.print("2");
                    sem1.release(); // 释放许可让线程1执行
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }).start();
    }
}
Mutex实现方案(基于synchronized+wait/notify)

通过synchronized互斥锁保证线程安全,配合wait/notify实现顺序控制:

public class MutexAlternate {
    private boolean turnToPrint1 = true; // 标记当前是否轮到线程1输出

    public static void main(String[] args) {
        MutexAlternate instance = new MutexAlternate();

        // 线程1:输出1
        new Thread(() -> {
            synchronized (instance) {
                while (true) {
                    try {
                        // 不是自己的轮次则等待
                        while (!turnToPrint1) {
                            instance.wait();
                        }
                        System.out.print("1");
                        turnToPrint1 = false;
                        instance.notify(); // 唤醒线程2
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        }).start();

        // 线程2:输出2
        new Thread(() -> {
            synchronized (instance) {
                while (true) {
                    try {
                        // 不是自己的轮次则等待
                        while (turnToPrint1) {
                            instance.wait();
                        }
                        System.out.print("2");
                        turnToPrint1 = true;
                        instance.notify(); // 唤醒线程1
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        }).start();
    }
}
Mutex实现方案(基于ReentrantLock+Condition)

使用显式锁ReentrantLock配合Condition更灵活地控制线程唤醒:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockAlternate {
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition condition1 = lock.newCondition();
    private final Condition condition2 = lock.newCondition();
    private boolean turnToPrint1 = true;

    public static void main(String[] args) {
        ReentrantLockAlternate instance = new ReentrantLockAlternate();

        // 线程1:输出1
        new Thread(() -> {
            lock.lock();
            try {
                while (true) {
                    while (!turnToPrint1) {
                        condition1.await();
                    }
                    System.out.print("1");
                    turnToPrint1 = false;
                    condition2.signal(); // 唤醒线程2
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                lock.unlock();
            }
        }).start();

        // 线程2:输出2
        new Thread(() -> {
            lock.lock();
            try {
                while (true) {
                    while (turnToPrint1) {
                        condition2.await();
                    }
                    System.out.print("2");
                    turnToPrint1 = true;
                    condition1.signal(); // 唤醒线程1
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                lock.unlock();
            }
        }).start();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 10:01:20