我想在 Java 中使用生产者-消费者模型将竞争条件复制到死锁

I want to replicate race condition into deadlock using the Producer-Consumer model in Java

在 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);
    }
}

使用此实现,应该会出现以下情况:

  1. 消费者刚刚读取了变量 itemCount,注意到它为零并且正要移动到 if 块内。

  2. 就在调用睡眠之前,消费者被中断,生产者被恢复。

  3. 生产者创建一个item,放入buffer,增加itemCount。

  4. 因为缓冲区在最后一次添加之前是空的,所以生产者试图唤醒消费者。

  5. 不幸的是消费者还没有睡觉,叫醒电话丢失了。当消费者恢复时,它进入休眠并且永远不会再被唤醒。这是因为消费者只有在itemCount等于1时才会被生产者唤醒。

  6. 生产者会一直循环直到缓冲区满,之后它也会进入休眠

我希望能够在 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
                }
            }
        }

    }