gpt4 book ai didi

Java 等待 - 在 while 循环内/外同步

转载 作者:行者123 更新时间:2023-11-30 08:18:46 25 4
gpt4 key购买 nike

我只是在解决消费者/生产者问题,让自己熟悉 Java 中的并发问题。我的问题可能与 C/P 问题本身有关。在下面的代码片段中,如果我使用版本 1,程序似乎运行良好,而使用版本 2,我似乎在可变时间后出现死锁。

我只会发布生产者类,因为不需要消费者类。

  • 缓冲区是生产者存放其输出的地方
  • 我只是在其中添加 1 的整数
  • while(true)是保持线程持续运行

我的问题是:我知道在 Java API 中调用 wait() 的结构是:synchronized -> while -> wait。但是在这种情况下会发生什么:while -> synchronized -> wait?如果在 wait() 期间,消费者调用 notifyAll() 并且生产者再次醒来,那么代码不会从调用 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();
}
}
}
}

最佳答案

关于同步要考虑的事情是“什么操作需要是原子的?”在您的示例中,check-then-wait 必须是原子的。否则,请考虑以下事件序列:

  • 线程 1:执行检查但失败
  • Thread2:更新缓冲区改变检查结果
  • 线程 2:调用通知
  • 线程 1:WAITING调用

在这种情况下,Thread1 错过了通知并阻塞,直到另一个通知到来。将检查放在同步块(synchronized block)中消除了这种可能性,因为线程 2 在线程 1 调用等待之前无法调用通知。

关于Java 等待 - 在 while 循环内/外同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27218779/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com