我想使用Java中的Producer-Consumer模型将竞争条件复制到死锁中

时间:2018-04-03 16:05:59

标签: java multithreading deadlock race-condition producer-consumer

在维基上,我发现生产者 - 消费者程序的以下伪代码,其竞争条件可能导致死锁:

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. 制作人创建一个项目,将其放入缓冲区,并增加itemCount。

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

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

  6. 生产者将循环,直到缓冲区已满,之后它也将进入休眠状态。

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

1 个答案:

答案 0 :(得分:1)

原因是您同步整个迭代步骤。 <{1}}下的两个代码块将按顺序运行。

你可以用以下方式复制它:

synchronized (this) {...}