Java线程公平策略如何工作?锁实现生产者消费者异常问题咨询
生产者-消费者锁实现的问题分析与修正
首先要指出你贴的代码里有两个致命错误:
- Condition的
await()调用必须在持有锁的状态下执行,你现在在lock.lock()之前就调用pCondition.await()和cCondition.await(),这会直接抛出IllegalMonitorStateException,所谓“开启公平策略能运行”大概率是巧合或者你实际运行的代码和贴出的不一致。 - 消费者方法里没有对
number做减一操作,消费后数量不变,逻辑完全错误。
回到你的疑问:不是必须依赖公平锁或await才能实现“生产1个立即消费”的逻辑,但必须用正确的等待唤醒机制,公平锁只是可选优化项。
核心逻辑说明
公平锁的作用是让线程按等待顺序获取锁,避免饥饿,但它不是实现交替生产消费的必要条件。而await()/signal()是Condition的核心机制,用来精准唤醒指定类型的线程,这是实现生产者消费者等待唤醒的标准方式——如果不用这类等待唤醒机制,线程只能不断轮询判断条件,不仅浪费CPU,还无法保证严格的交替执行(因为线程调度是操作系统决定的,非公平锁下可能会出现同一个线程重复获取锁的情况)。
修正后的正确代码(非公平锁也能正常运行)
public class ProductLockDemo2 { private Integer number = 0; // 使用非公平锁,性能更高 private Lock lock = new ReentrantLock(false); private Condition pCondition = lock.newCondition(); private Condition cCondition = lock.newCondition(); public Integer getNumber() { return number; } public void setNumber(Integer number) { this.number = number; } public void produce() throws InterruptedException { lock.lock(); try { // 用while循环防止虚假唤醒(单个if可能被异常唤醒导致逻辑错误) while (getNumber() >= 10) { pCondition.await(); } number++; System.out.println("producing number :" + number); Thread.sleep(1000); // 唤醒等待的消费者线程 cCondition.signal(); } finally { lock.unlock(); } } public void consume() throws InterruptedException { lock.lock(); try { while (getNumber() <= 0) { cCondition.await(); } System.out.println("consuming:" + number); Thread.sleep(1000); number--; // 补充消费后的数量递减 // 唤醒等待的生产者线程 pCondition.signal(); } finally { lock.unlock(); } } }
修正要点
- 所有同步逻辑必须放在
lock.lock()和lock.unlock()之间,确保操作的原子性 - 用
while循环判断条件,避免虚假唤醒(JVM允许线程在没有被signal的情况下唤醒) - 消费者方法补充
number--,修正逻辑错误 - 即使使用非公平锁,只要等待唤醒逻辑正确,依然能严格实现“生产一个、消费一个”的交替执行逻辑
内容的提问来源于stack exchange,提问作者keepmoving
相关产品推荐
相关产品推荐

