我正在尝试使用可重入锁来实现典型的生产者消费者。 生产者线程打印偶数,消费者线程打印奇数。 这是我的代码,但由于某种原因它陷入了僵局 可运行的任务
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 ,但这些概念都直接映射到Lock
和 Condition
对象。)
您的基本问题是您的两个线程不能彼此完全对称。其中一个必须先行。你的 main() 线程必须唤醒其中一个,或者用“你先”的参数构造一个线程。
关于java - 为什么我的生产者消费者死锁(或活锁)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47057971/