为了账号安全,请及时绑定邮箱和手机立即绑定

使用 ReentrantLock 时出现死锁

使用 ReentrantLock 时出现死锁

守候你守候我 2022-07-06 19:10:42
我使用 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 在生产者方法中我会不会没事在运行堆转储时Reference Handler" #2 daemon prio=10 os_prio=31 cpu=0.26ms elapsed=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为什么即使在我使用释放锁后它也会死锁    condn.signal();
查看完整描述

2 回答

?
九州编程

TA贡献1785条经验 获得超4个赞

如果消费者consume先调用然后生产者调用produce,那么生产者将错过signal并卡住。



查看完整回答
反对 回复 2022-07-06
?
慕沐林林

TA贡献2016条经验 获得超9个赞

你可以用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()需要互斥访问和/或注册方相应更改(取决于您需要什么语义)


查看完整回答
反对 回复 2022-07-06
  • 2 回答
  • 0 关注
  • 210 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信