![](/img/trans.png)
[英]Java Lock Condition Wait and Notify: IllegalMonitorStateException
[英]How to use a lock in Java to wait for the special condition?
我有一個對象:
public class Resource {
private Lock lock = new ReentrantLock();
private boolean processed = false;
public Lock getLock() {
return lock;
}
public boolean isProcessed() {
return processed;
}
public void setProcessed(boolean processed) {
this.processed = processed;
}
}
我想停止線程“一”,直到線程“二”將變量“已處理”更改為真。 在“已處理”設置為 true 后,我想喚醒線程“一”並繼續做一些事情。
我知道我們可以使用 wait 和 notify 方法來組織它,但是由於中斷而非常危險。
如果我只使用 wait 和 notify 方法,可能會出現無限等待的情況。
如果我們的 wait 方法因某種原因被中斷,我們會檢查“process”變量是否仍然為假,然后我們可以再次使用 wait ,如下所示:
while(true){
if(!resource.isProcessed()){
resource.getLock().wait();
}
else{
break;
}
}
使用這樣的代碼是很危險的,因為在我們檢查“!resource.isProcessed()”之后,在我們使用“resource.getLock().wait()”之前,另一個進程可以將“process”設置為true並調用“resource .getLock().notify()”(這不會生效,因為我們還沒有調用“wait()”)。
如何安全地等待某個條件? 如何安全地通知/解鎖某些情況?
正如Peter Lawrey在評論中回答的那樣,Java 中有可用的Condition 。 (謝謝指點)
這是文檔中提供的示例的副本:
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
您可以使用CountDownLatch使一個線程等待,直到另一個線程執行的操作完成。
假設 T1 和 T2 是您的線程,並且它們共享一個初始化為1
的計數器的CountDownLatch
。 T1 將首先在閂鎖上await()
,而 T2 應執行其操作,然后在閂鎖上調用countDown()
以讓 T1 繼續進行。
當然t1中的await()
仍然可以被中斷,所以你可能想循環調用它。
class T1 implements Runnable {
private final CountDownLatch latch;
T1(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
awaitUninterruptibly(latch);
doWork();
}
private void awaitUninterruptibly(CountDownLatch latch) {
boolean interrupted = false;
try {
while (true) {
try {
latch.await();
return;
} catch (InterruptedException e) {
interrupted = true;
}
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}
}
class T2 implements Runnable {
private final CountDownLatch latch;
T1(CountDownLatch latch) {
this.latch = latch;
}
public void run() {
doWork();
latch.countDown();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.