在Wiki上,我找到了以下生产者 - 消费者程序的伪代码,该计划具有可能导致僵局的种族条件:
int itemCount = 0;
procedure producer()
{
while (true)
{
item = produceItem();
if (itemCount == BUFFER_SIZE)
{
sleep();
}
putItemIntoBuffer(item);
itemCount = itemCount + 1;
if (itemCount == 1)
{
wakeup(consumer);
}
}
}
procedure consumer()
{
while (true)
{
if (itemCount == 0)
{
sleep();
}
item = removeItemFromBuffer();
itemCount = itemCount - 1;
if (itemCount == BUFFER_SIZE - 1)
{
wakeup(producer);
}
consumeItem(item);
}
}
使用此实现,应发生以下情况:
消费者刚刚读取了变量ItemCount,注意到它为零,并且即将在IF块内移动。
在打电话睡眠之前,消费者被中断并恢复生产者。
生产者创建一个项目,将其放入缓冲区并增加Itemcount。
因为缓冲区在上次添加之前是空的,所以生产者试图唤醒消费者。
不幸的是,消费者尚未睡觉,并且唤醒电话丢失了。当消费者恢复时,它会入睡,再也不会唤醒。这是因为只有当itemcount等于1时,消费者才被生产者唤醒。
生产者将循环直到缓冲区饱满,之后它也将入睡。
我希望能够在Java中复制此功能,但是到目前为止,我在运行程序多次后无法进行。这是我的代码:
private LinkedList<Integer> sharedList = new LinkedList<Integer>();
private int sharedValue = 0;
private int MAX_LIMIT = 10;
public void produce() throws InterruptedException {
Random random = new Random();
while (true) {
synchronized (this) {
if (sharedValue == MAX_LIMIT) { //'produce' thread waits if list is full
wait();
}
sharedValue = sharedValue + 1;
sharedList.add(sharedValue); System.out.println("added value: " + sharedValue);
if (sharedValue == 1) {
notify(); //notifies 'consume' thread if list is not empty
}
}
}
}
public void consume() throws InterruptedException {
Random random = new Random();
while (true) {
synchronized (this) {
if (sharedValue == 0) { //'consume' waits if list is empty
wait();
}
sharedValue = sharedValue - 1;
sharedList.remove(); System.out.println("removed value: " + sharedValue);
if (sharedValue == MAX_LIMIT-1) {
notify(); //notifies 'produce' if list is not full
}
}
Thread.sleep(random.nextInt(1000));
}
}
原因是您同步整个迭代步骤。synchronized (this) {...}
下的两个代码块将顺序运行。
您可以用:
复制它 private LinkedList<Integer> sharedList = new LinkedList<Integer>();
private volatile int sharedValue = 0;
private int MAX_LIMIT = 10;
public void produce() throws InterruptedException {
while (true) {
if (sharedValue == MAX_LIMIT) { //'produce' thread waits if list is full
synchronized (this) {
wait();
}
}
synchronized (this) {
sharedValue = sharedValue + 1;
sharedList.add(sharedValue);
System.out.println("added value: " + sharedValue);
}
if (sharedValue == 1) {
synchronized (this) {
notify(); //notifies 'consume' thread if list is not empty
}
}
}
}
public void consume() throws InterruptedException {
while (true) {
if (sharedValue == 0) { //'consume' waits if list is empty
synchronized (this) {
wait();
}
}
synchronized (this) {
sharedValue = sharedValue - 1;
sharedList.remove();
System.out.println("removed value: " + sharedValue);
}
if (sharedValue == MAX_LIMIT - 1) {
synchronized (this) {
notify(); //notifies 'produce' if list is not full
}
}
}
}