java - 为什么我的生产者消费者死锁(或活锁)?

标签 java multithreading concurrency

我正在尝试使用可重入锁来实现典型的生产者消费者。 生产者线程打印偶数,消费者线程打印奇数。 这是我的代码,但由于某种原因它陷入了僵局 可运行的任务

public class EvenPrinterRunnable  implements Runnable {
    SharedBuffer buf;
    public EvenPrinterRunnable(SharedBuffer buf) {
        this.buf = buf;

        Thread.currentThread().setName("Even Runnable");
    }

    @Override
    public void run() {

        for(int i = 0; i < 10; i++) {
            buf.printEven();
        }

    }
}

public class OddPrinterRunnable implements Runnable {
    SharedBuffer buf;
    public OddPrinterRunnable(SharedBuffer buf){
        this.buf = buf;
        Thread.currentThread().setName("ODD Runnable");
    }

    @Override
    public void run(){
        for(int i = 0; i < 10; i++){
            buf.printOdd();
        }
    }
}

共享缓冲区

public class SharedBuffer {
    Lock lock = new ReentrantLock();

    Condition evenNotPrinted = lock.newCondition();
    Condition oddNotPrinted  = lock.newCondition();

    int currentNumber = 0;

    public void printEven() {
        System.out.println("from even");
        try {
            lock.lock();
            try {
                oddNotPrinted.await();
            }
            catch(InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(" being printed by thread " + "" + Thread.currentThread().getName() + " "+ currentNumber);
            currentNumber++;
            evenNotPrinted.signalAll();
        }
        finally {
            lock.unlock();
        }
    }

    public void printOdd() {
        System.out.println("from odd");
        try {
            lock.lock();
            try {
                evenNotPrinted.await();
            }
            catch(InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(" being printed by thread " + "" + Thread.currentThread().getName() + " "+ currentNumber);
            currentNumber++;
            oddNotPrinted.signalAll();
        }
        finally {
            lock.unlock();
        }
    }
}

驱动程序类

public class OddEvenDriver {
    public static void main(String[] args) {

        //using runnables with lock buffer

        SharedBuffer buf1 = new SharedBuffer();
        EvenPrinterRunnable epr = new EvenPrinterRunnable(buf1);
        OddPrinterRunnable opr = new OddPrinterRunnable(buf1);

        ExecutorService es = Executors.newFixedThreadPool(2);
        es.submit(opr);
        es.submit(epr);
        es.shutdown();
    }
}

正在输出

from even
from odd

或者

from odd
from even

这意味着每个线程都在获取锁,然后等待条件 EvenNotPrinted 和 oddNotPrinted,并且由于在调用信号之前它们中没有一个可以继续进行,所以我的问题是,我应该在开始时向每个条件发出信号吗?方法本身? 我在这里缺少什么

最佳答案

So my question is , shall I signal each condition at the start of the method itself?

没有。那是行不通的。条件变量不记得它之前在线程调用 condition.await() 时收到的信号。 condition.signal()condition.signalAll() 函数根本不执行任何操作,除非其他线程已经在等待信号。

条件变量是一种低级同步机制,旨在以非常具体的方式使用来实现队列和信号量以及其他高级同步对象。 Guarded Blocks tutorial详细解释一下。 (注意:本教程讨论了 object.wait()object.notify() 以及 synchronized block ,但这些概念都直接映射到LockCondition 对象。)

您的基本问题是您的两个线程不能彼此完全对称。其中一个必须先行。你的 main() 线程必须唤醒其中一个,或者用“你先”的参数构造一个线程。

关于java - 为什么我的生产者消费者死锁(或活锁)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47057971/

相关文章:

java - 如何在并发环境中设计到数据库的http连接(是否为静态变量)

Java:第二个窗口是空白的

java - 链接列表程序不会删除对象,并且会因未知原因抛出强制转换异常?

python - 异步交互式 Python 脚本

c# - 在与服务线程不同的线程上运行服务操作

java - Java UDP多线程通信的一个问题

java - 使用 ReentrantReadWriteLock 和 boolean 标志

java - 如何检查不同步工作的多个线程的功能

java - 使用句子检测器评估工具时,OpenNLP 如何计算漏报?

java - 从多个列表中生成所有可能的组合