使用 ReentrantLock 时出现死锁

我使用 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();


守候你守候我
浏览 254回答 2
2回答

九州编程

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

慕沐林林

你可以用Phaser它。关键是Phaser制片人问“我错过了一些消费吗?” 如果不是,它正在等待,如果是,它会立即继续进行。这是一个例子:public class Processor {&nbsp; &nbsp;private final Phaser phaser = new Phaser(1);&nbsp; &nbsp;private volatile int lastPhaseId = 0;&nbsp; &nbsp; public void produce() throws InterruptedException{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("inside producer method");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lastPhaseId = phaser.awaitAdvance(lastPhaseId);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("thread again wakeup");&nbsp; &nbsp; }&nbsp; &nbsp; public void consume() throws InterruptedException{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Thread.sleep(1000);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; phaser.arrive();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("will i ever be ok ");&nbsp; &nbsp; }}这适用于单个消费者的情况。如果假设有多个消费者,则phase.arrive()需要互斥访问和/或注册方相应更改(取决于您需要什么语义)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java