此代码中是否发生死锁? [英] Does any deadlock occur in this code?

查看:76
本文介绍了此代码中是否发生死锁?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑传统的生产者/消费者线程示例.当使用者检查缓冲区大小不为零时,是否有必要在等待锁定之前向其他线程发出信号? 这是方法代码:

public void consume()
{
    lock(_lock)
    {
        while(buf.Count == 0)
        {
             // Is there any need to *Monitor.Pulse(_lock);* here?
             Monitor.Wait(_lock);
        }
        // Consume
    }
}

public void produce()
{
    lock(_lock)
    {
        // Produce
        buf.Insert(item);
        Monitor.PulseAll(_lock);
    }
}

解决方案

不,不会死锁:

  • 一旦生产者获得了锁,它就会立即释放它(脉冲不会中断生产者)
  • 一旦消费者获得了锁,它要么找到数据,要么适当地等待(释放锁)

在任何情况下,生产者最终都无法等待无法获得的锁.但是,我要说使用者中的PulseAll没有明显的目的.要回答您的其他问题:

在等待锁定之前是否有必要向其他线程发送信号

什么都没有,实际上这样做是一个非常糟糕的主意.因为如果您这样做了,即使没有任何有用的工作要做,两个使用者也可以使永远唤醒对方.

唯一有用的脉搏是在您有理由相信某人正在等待并且现在可以做某事时.如果缓冲区先前为空(即if(buf.Count == 1)),您实际上可以将其减小为仅脉冲-因为如果缓冲区不为空,则可能没有人在等待. /p>

Consider traditional producer/consumer threading example. When consumer checks for buffer size not to be zero, is there any need to signal other threads before waiting on lock? Here is methods code:

public void consume()
{
    lock(_lock)
    {
        while(buf.Count == 0)
        {
             // Is there any need to *Monitor.Pulse(_lock);* here?
             Monitor.Wait(_lock);
        }
        // Consume
    }
}

public void produce()
{
    lock(_lock)
    {
        // Produce
        buf.Insert(item);
        Monitor.PulseAll(_lock);
    }
}

解决方案

No, that won't deadlock:

  • once the producer can get the lock, it releases it promptly (the pulse doesn't interrupt the producer)
  • once the consumer can get the lock, it either finds data, or it waits (releasing the lock) appropriately

There is no scenario where the producer ends up waiting on an unobtainable lock. I would, however, say that the PulseAll in the consumer serves no obvious purpose. To answer your other question:

is there any need to signal other threads before waiting on lock

None whatsoever, and in fact it would be a very bad idea to do so. Because if you did this, two consumers could keep waking each-other up forever, even though there is no useful work to do.

The only time it is useful to pulse is when you have reason to believe that someone is waiting, and can now do something. You could actually probably reduce it to only pulse if the buffer was previously empty (i.e. if(buf.Count == 1)) - because if it wasn't empty, presumably nobody is waiting.

这篇关于此代码中是否发生死锁?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆