【发布时间】:2014-11-30 22:02:42
【问题描述】:
我只是在处理消费者/生产者问题,以便熟悉 Java 中的并发问题。我的问题可能与 C/P 问题本身相邻。在下面的代码 sn-ps 中,如果我使用版本 1,程序似乎运行良好,而使用版本 2 我似乎在一段时间后出现死锁。
我只会发布 Producer 类,因为不需要 Consumer 类。
- 缓冲区是生产者存放其输出的地方
- 我只是在其中添加 1 的整数
- while(true) 是保持线程连续运行
我的问题是:我知道在 Java API 中调用 wait() 的结构是:同步 -> while -> 等待。但是在这种情况下会发生什么:while -> synchronized -> wait?如果在 wait() 期间,Consumer 调用 notifyAll() 并且 Producer 再次唤醒,那么代码不会从调用 wait() 的地方继续,最终它会到达 while(buffer.remainingCapacity() == 0) ?
我已经完成了四处挖掘,看看之前是否有人问过这个问题,但找不到任何具体的内容。
版本 1
public class Producer extends Thread {
ArrayBlockingQueue<Integer> buffer = new ArrayBlockingQueue<>(10);
public Producer(ArrayBlockingQueue<Integer> buffer) {
this.buffer = buffer;
}
@Override
public void run() {
while (true) {
synchronized(buffer) {
while (buffer.remainingCapacity() == 0) {
try {
buffer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
try {
synchronized (buffer) {
buffer.add(1);
System.out.println("Producer active with remaining capacity: " + buffer.remainingCapacity());
buffer.notifyAll();
}
} catch (IllegalStateException ex) {
ex.printStackTrace();
}
}
}
}
第 2 版
public class Producer extends Thread {
ArrayBlockingQueue<Integer> buffer = new ArrayBlockingQueue<>(10);
public Producer(ArrayBlockingQueue<Integer> buffer) {
this.buffer = buffer;
}
@Override
public void run() {
while (true) {
while (buffer.remainingCapacity() == 0) {
synchronized (buffer) {
try {
buffer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
try {
synchronized (buffer) {
buffer.add(1);
System.out.println("Producer active with remaining capacity: " + buffer.remainingCapacity());
buffer.notifyAll();
}
} catch (IllegalStateException ex) {
ex.printStackTrace();
}
}
}
}
只是为了它,这是另一个版本代码,似乎可以解决问题。我只是把它放在这里,以防它对其他人有帮助,或者如果有人可以告诉我它是否错误以及为什么。与上面的版本相比,当涉及到它们的位置时,代码中的 wait 和 notifyAll 方法“翻转”了。
while(true) {
while(buffer.remainingCapacity() == 0){
synchronized (buffer){
buffer.notifyAll();
}
}
try {
buffer.add(1);
System.out.println("Producer active with remaining capacity: " + buffer.remainingCapacity());
} catch (IllegalStateException ex) {
synchronized (buffer){
try {
buffer.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
【问题讨论】:
-
在
synchronized块内调用buffer.remainingCapacity显然是错误的吗?
标签: java multithreading wait