使用ReentrantLock实施生产者消费者问题
public class Processor {
Lock lock = new ReentrantLock(true);
Condition condn = lock.newCondition();
public void produce() throws InterruptedException{
lock.lock();
System.out.println("inside producer method");
condn.await();
System.out.println("thread again wakeup");
lock.unlock();
}
public void consume() throws InterruptedException{
lock.lock();
Thread.sleep(1000);
condn.signal();
System.out.println("will i ever be ok ");
lock.unlock();
}
}
ReentrantLock同步了两种方法,但有时该进程与之死锁了
o / p 我会好起来吗 内部生产者方法
运行堆转储
引用处理程序”#2守护程序prio = 10 os_prio = 31 cpu = 0.26ms经过的时间= 540.35s tid = 0x00007fd5f186f800 nid = 0x4603等待条件[0x0000700002357000]
java.lang.Thread.State: RUNNABLE
at java.lang.ref.Reference.waitForReferencePendingList(java.base@11.0.1/Native Method)
at java.lang.ref.Reference.processPendingReferences(java.base@11.0.1/Reference.java:241)
at java.lang.ref.Reference$ReferenceHandler.run(java.base@11.0.1/Reference.java:213)
"Finalizer" #3 daemon prio=8 os_prio=31 cpu=0.67ms elapsed=540.35s tid=0x00007fd5f1883000 nid=0x4303 in Object.wait() [0x000070000245a000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(java.base@11.0.1/Native Method)
- waiting on <0x0000000787f08f80> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(java.base@11.0.1/ReferenceQueue.java:155)
- waiting to re-lock in wait() <0x0000000787f08f80> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(java.base@11.0.1/ReferenceQueue.java:176)
at java.lang.ref.Finalizer$FinalizerThread.run(java.base@11.0.1/Finalizer.java:170)
"Signal Dispatcher" #4 daemon prio=9 os_prio=31 cpu=0.34ms elapsed=540.27s tid=0x00007fd5f1884000 nid=0x3903 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Thread-0" #12 prio=5 os_prio=31 cpu=1.72ms elapsed=540.07s tid=0x00007fd5f00c7000 nid=0xa303 waiting on condition [0x0000700002d75000]
java.lang.Thread.State: WAITING (parking)
at jdk.internal.misc.Unsafe.park(java.base@11.0.1/Native Method)
- parking to wait for <0x0000000787ed4030> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(java.base@11.0.1/LockSupport.java:194)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(java.base@11.0.1/AbstractQueuedSynchronizer.java:2081)
at Processor.produce(Processor.java:11)
at RunnableExample$1.run(RunnableExample.java:13)
at java.lang.Thread.run(java.base@11.0.1/Thread.java:834)
为什么即使我使用释放了锁,它也会变得死锁
condn.signal();
答案 0 :(得分:1)
如果消费者先致电consume
,然后生产者致电produce
,则生产者将错过signal
并陷入困境。
答案 1 :(得分:0)
您可以使用Phaser
。问题在于,对于Phaser
,生产者会问“我错过了一些消费吗?”如果否,则等待,如果是,则立即继续处理。这是一个示例:
public class Processor {
private final Phaser phaser = new Phaser(1);
private volatile int lastPhaseId = 0;
public void produce() throws InterruptedException{
System.out.println("inside producer method");
lastPhaseId = phaser.awaitAdvance(lastPhaseId);
System.out.println("thread again wakeup");
}
public void consume() throws InterruptedException{
Thread.sleep(1000);
phaser.arrive();
System.out.println("will i ever be ok ");
}
}
这在单个消费者的情况下有效。如果假设有多个使用者,phase.arrive()
需要互斥访问和/或注册方进行了相应更改(取决于您需要的语义)