リエントラントロックを使用して典型的なプロデューサコンシューマを実装しようとしています。 プロデューサスレッドは偶数を出力し、コンシューマスレッドは奇数を出力します。共有バッファプロデューサのコンシューマがデッドロック(またはライブロック)するのはなぜですか?
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();
}
}
それは
を出力しているドライバクラス は、ここに私のコードですが、いくつかの理由では 実行可能なタスク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();
}
}
}
がデッドロックされます
from even
from odd
各スレッドがロックを取得しているし、それが条件evenNotPrintedとoddNotPrintedに待機し、信号が呼び出されるまで、それらの誰もが進行しないことができるので、だから私の質問はある意味
from odd
from even
、ものと私はメソッド自体の開始時に各条件に合図しますか? 私はここで紛失しています
'signal()'が呼ばれた後に 'await()'に達する可能性はありますか? – daniu
これは合理的には明らかです:各スレッドはロックを獲得しようとしていて、もう一方がロックを取得してシグナルを受信した後に*送信するシグナルを待っています。最初のスレッドはロックを取得し、その信号を待ちます。 2番目のスレッドはロックを取得できません。だからデッドロックです。 –
はい、ありがとうございました、私はそれが問題であることを理解しましたが、私はこのイディオムが頻繁に使用されるのを見ました。私は何が欠けていたのだろうと思っていた。 – TruckDriver