在处理经典的多个消费者/生产者问题时,我遇到了一个问题,即如何避免在插入圆形缓冲区或从圆形缓冲区中移出时出现竞争状况。提前感谢您的帮助!
用于示例的循环缓冲区的示例代码。与我的实现类似(注意:我不能使用集合类型,只能使用数组):
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BoundedBuffer {
private final String[] buffer;
private final int capacity;
private int front;
private int rear;
private int count;
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
public BoundedBuffer(int capacity) {
super();
this.capacity = capacity;
buffer = new String[capacity];
}
public void deposit(String data) throws InterruptedException {
lock.lock();
try {
while (count == capacity) {
notFull.await();
}
buffer[rear] = data;
rear = (rear + 1) % capacity;
count++;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public String fetch() throws InterruptedException {
lock.lock();
try {
while (count == 0) {
notEmpty.await();
}
String result = buffer[front];
front = (front + 1) % capacity;
count--;
notFull.signal();
return result;
} finally {
lock.unlock();
}
}
}
我需要知道的是如何实现一种检查缓冲区是否为空/空的方法?此方法需要包含在此BoundedBuffer中,并且在继续进行/调用插入/编写方法之前,必须从另一个类(生产者/消费者)中调用此方法。
Producer类中方法的伪代码。
if (!bufferFull) {
buffer.addelement;
}
else {
thread.sleep(5)
threadHasSleptFor++;
}
我正在使用线程,并且有多个生产者/消费者(在这种情况下为2个生产者/消费者,但我可能需要更多)。我需要它,以便如果缓冲区已满,线程必须等待直到可以插入为止,并且需要存储其等待时间以用于输出(非调试,这是核心功能的一部分)。我遇到的问题是这样的:
Java方面有些新知识,但据我了解,这是“检查时间/使用时间”竞争条件问题。
有人可以建议如何安全地实现它,以及如何循环代码,以便threadHasSleptFor变量在每次失败时都保持递增状态(提供方法会很棒)。我想要它,以便只有请求检查的线程可以开始插入项目;第二个生产者必须等待锁。
谢谢。
根据定义,如果没有更高级别的锁定,这是不可能做到的。
从线程的角度来看,您必须保证检查缓冲区是否已满以及以下插入是否是原子的,这意味着您必须获取一些公共锁才能这样做。这个普遍的问题的确称为检查时间到使用时间,并导致许多有趣的比赛条件。
这些问题的解决方案是不检查是否可以先执行某项操作,然后再执行该操作,而只是尝试执行该操作并处理错误情况。因此,如果您不想在缓冲区的操作已满时阻塞,只需实现一个tryDeposit
方法,如果该方法无法存储值,则该方法将引发异常,或者返回布尔值成功值。
尽管在您的情况下,如果您必须存储将值压入堆栈之前所需的时间,我不明白为什么会这样简单:
long start = System.nanotime();
queue.deposit();
long end = System.nanotime();
也不会成功。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句