困惑于锁定,等待,脉冲等

时间:2013-11-07 23:39:24

标签: c# multithreading

我理解线程的基础知识以及如何发生死锁。我知道你想按特定的顺序取出锁,以确保你不会让自己进入一个循环的射击队。

我的大脑遇到麻烦的是该命令是如何保证的,以及等待和脉冲(脉冲)如何协助。

请勿回复skeet's多线程文章的链接,因为这是我来自的地方。我也用谷歌搜索了这个post.

在Jon的教程中,方法Produce()和Consume都锁定了listlock,我看不到如何维护订单。无论顺序如何,一方击败对方,另一方如何获得锁定?它不正确......所以最后尝试锁定的线程会阻塞,直到第一个线程进入脉冲或等待取决于?

所以不确定我是否在寻找其他文章,在上面的SO文章中,我采取了gatopeich与老板,工人和锁定对象的电话回答。

工作人员在工作时锁定电话。当他有锁(同时)是真的)他解锁???带有monitor.wait语句的电话.... ???

与此同时,老板锁定了电话......但是等一下,如果员工按时上班并在老板到达之前锁上电话......?

乔恩指出,如果你不理解这一点,你会认为它会陷入僵局,这正是我所处的位置:

  

重复一遍:调用Wait会解锁您正在等待的监视器。这是一个重要的观点,因为否则代码看起来就像死锁一样!

所以我很抱歉这么密集,把它当作鸡肉或鸡蛋的情景。显然,在指定获取锁的顺序以避免死锁时,必须有一些我不理解线程如何交互的东西。

感谢您的帮助和耐心。

1 个答案:

答案 0 :(得分:2)

没有保证获得锁定的顺序。您不需要它来确定死锁。有四个条件,当所有活动都会导致死锁时。

  1. 相互排斥:必须有两个无法共享的资源(因此您必须锁定)。

  2. 保持并等待:进程锁定一个资源并请求锁定另一个资源。

  3. 没有先发制人:操作系统无法从持有它们的进程中窃取锁定(通过重新启动进程等)。

  4. 循环等待:线程A在等待D时锁定C而线程B在等待C时锁定D.

  5. 如果这些条件中的任何一个不成立,则不会出现死锁。是的,我主要从Wikipedia获取此信息。

    Jon的例子中没有两个资源。只有一个锁。没有保持和等待,因为没有第二个锁试图锁定。第三个条件确实让我相信Windows。由于没有两个锁,因此无法维持循环等待。因此,不会出现僵局。条件1,2和4不成立。是的,消费者可能只是启动无限循环而且会“僵局”,但没有人会这样做。

    Jon的例子只生成一个消费者。然后每隔一秒左右(他将它随机化,所以它并不总是第二次)生产者试图锁定。消费者每隔一秒左右就会试图锁定一次。这两次完全不相关。它们位于具有不同种子的不同随机数生成器的不同线程上。你不能在多次运行中绘制它们之间的一致关系(呃,也许你可以因为种子不会改变)。

    当消耗尝试获取锁定时,它会检查是否有任何消耗。如果没有,它只是等待(此时每秒重启消耗过程)。这将释放锁并允许生产者接受它。所以无论是获取对象还是等待。

    当生产者试图获取锁定时,它会阻塞,直到没有消费者持有锁定(并且如果没有任何东西可以消耗,所有消费者将很快为生产者取消锁定的方式,因此它将很容易锁定一旦消耗完所有)。然后它获取锁定,将对象放入队列,并唤醒等待的消费者。

    这无限期地持续(或者在Jon的情况下为10次)。有限数量的消费者进来,当队列中没有任何东西时(通过等待)离开。当所有消费者都在等待并将对象放入队列时,生产者进入。然后生产者唤醒消费者并阻止(通过调用脉冲)。一切都重新开始。

    简短回答:为什么要脉冲等待?

    1. Pulse让消费者接管锁,然后线程休眠足够长时间以便消费者获得锁
    2. 等待,由所有消费者调用(在这种情况下为1),释放锁定和阻止,直到生产者发出脉冲,这通常发生在Jon的情况下
    3. 消费者线程不自私。如果它不能做任何事情,它让生产者线程与球一起玩。然后生产者线程只玩球足够长的时间在其上贴上它想要向消费者展示的贴纸。它向消费者大吼大叫并说“嘿看看这个贴纸”,然后远离球,所以消费者可以看看并撕掉球上的贴纸。冲洗并重复(球现在可能有细菌;)。