[英]Blocked using wait() and notify() in Java
我正在使用Java中的wait()
和notify()
編寫生產者和消費者代碼。 創建Thread-0並在produce()
上調用,並創建Thread-1並在consume()
上調用。
public class Processor {
private volatile List<Integer> list = new ArrayList<>();
private final int MAX_CAPACITY = 5;
Object lock = new Object();
public void produce() throws InterruptedException {
while (true) {
while (list.size() == MAX_CAPACITY) {
System.out.println("List is full! Producer is Waiting....");
synchronized (lock) {
lock.wait();
}
}
synchronized (lock) {
int random = new Random().nextInt(100);
list.add(random);
System.out.println("Added to list:" + random);
lock.notify();
}
}
}
public void consume() throws InterruptedException {
while (true) {
while (list.size() == 0) {
System.out.println("List is empty!! Consumer is Waiting...");
synchronized (lock) {
lock.wait();
}
}
synchronized (lock) {
int i = list.remove(0);
System.out.println("Removed from list:" + i);
lock.notify();
}
}
}
}
問題是在執行期間,程序在produce()
之后停止:
List is empty!! Consumer is Waiting...
Added to list:22
Added to list:45
Added to list:72
Added to list:91
Added to list:51
List is full! Producer is Waiting....
我無法理解這里的問題是什么。 我以某種方式弄清楚將while
循環中的代碼包裝在produce()
和consume()
中的synchronized
塊中解決了這個問題。
produce()
synchronized (lock) {
while (list.size() == MAX_CAPACITY) {
System.out.println("List is full! Producer is Waiting....");
lock.wait();
}
consume
synchronized (lock) {
while (list.size() == 0) {
System.out.println("List is empty!! Consumer is Waiting...");
lock.wait();
}
}
這是什么問題? 這是線程飢餓還是死鎖的情況?
編輯:調用類:
public class App {
public static void main(String[] args) {
final Processor processor = new Processor();
Runnable r1 = new Runnable() {
@Override
public void run() {
try {
processor.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable r2 = new Runnable() {
@Override
public void run() {
try {
processor.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
當你執行list.size()
它不是線程安全的,並且沒有保證你將看到另一個線程中的值發生了變化。 如果JIT檢測到您沒有在該線程中更改它,則它甚至可以內聯該值。
通過將synchronized
塊放在循環外部,可確保值的變化可見(因為它也在while(true)
循環內while(true)
。
使用synchronized
外部循環創建讀取障礙 。 因此,生產者/消費者將在您檢查list.size()
環路中看到最新的list
。 這就是為什么你移動后,它的工作原理while
內循環synchronized
塊。
在您的情況下,我還建議您在生產者/消費者中使用單個同步塊。
例如,在您的實現中,如果list.size() == 0
對於使用者變為false
,它將釋放對lock
對象的鎖定,然后在下一個語句中嘗試再次獲取鎖定以消耗數據,這是不必要且低效的。 應該是這樣的:
public void consume() throws InterruptedException {
while (true) {
synchronized (lock) {
while (list.size() == 0) {
System.out.println("List is empty!! Consumer is Waiting...");
lock.wait();
}
int i = list.remove(0);
System.out.println("Removed from list:" + i);
lock.notify();
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.