0

我了解线程的基础知识以及死锁是如何发生的。我了解您希望按特定顺序打开锁,以帮助确保您不会陷入循环行刑队。

我的大脑遇到的问题是如何保证该顺序以及究竟如何等待和脉冲(pulseall)辅助。

不要回答skeet关于多线程的文章的链接,因为我就是从那里来的。我也用谷歌搜索了所以并想出了这篇文章。

在 Jon 的教程中,Produce() 和 Consume 方法都锁定在 listlock 上,我看不到订单是如何维护的。不管命令一个人击败另一个人,那么另一个人如何获得锁定?不对...所以最后一个尝试锁定的线程坐在那里阻塞,直到第一个到达脉冲或等待取决于?

所以不确定我寻找其他文章,在上面的 SO 文章中,我带着老板、工人和锁定的对象电话回答了 Gatopeich 的问题。

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

同时老板锁手机……但是等下,员工怎么能准时上班,在老板赶到之前锁手机……?

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

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

所以我很抱歉如此密集并将其视为鸡或蛋的场景。显然,在指定获取锁的顺序以避免死锁时,我不了解线程如何交互。

感谢您的帮助和耐心。

4

1 回答 1

2

谁获得锁没有保证的顺序。您不需要它来确定死锁。有四种情况,当所有情况都处于活动状态时,会导致死锁。

  1. 互斥:必须有两个资源不能共享(所以你必须锁定)。

  2. 持有并等待:一个进程正在锁定一个资源并为另一个请求锁定。

  3. 无抢占:操作系统无法从持有它们的进程中窃取锁(通过重新启动进程等)

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

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

Jon 的示例中没有两个资源。只有一把锁。没有持有和等待,因为没有第二个锁可以尝试锁定。第三个条件确实成立,但我相信 Windows。并且不能维持循环等待,因为没有两个锁。因此,不可能出现死锁。条件 1、2 和 4 不成立。是的,消费者可以启动一个无限循环,它会“死锁”,但没有人会这样做。

Jon 的示例只产生了一个消费者。然后每隔一秒左右(他将其随机化,因此并不总是一秒)生产者尝试获取锁定。此外,消费者每隔一秒左右就会尝试锁定。这两次是完全无关的。它们位于不同的线程上,具有不同的随机数生成器和不同的种子。您无法在多次运行中绘制出它们之间的一致关系(嗯,也许您可​​以,因为种子不会改变)。

当消费尝试获取锁时,它会检查是否有任何东西要消费。如果没有,它只是等待(此时它不会每秒重新启动消费进程)。这将释放锁并允许生产者获取它。所以它要么得到一个对象,要么等待。

当生产者尝试获取锁时,它会阻塞,直到没有消费者持有锁(如果没有任何东西可以消费,所有消费者都会迅速为生产者获取锁扫清道路,因此一旦一切就绪,它就会轻松获取锁消耗)。然后它获取锁,将一个对象放入队列,并唤醒等待的消费者。

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

简短的回答:为什么要脉动并等待?

  1. Pulse 让消费者接管锁,然后线程休眠足够长的时间让消费者获得锁
  2. 等待,由所有消费者(在本例中为 1)调用,释放锁并阻塞,直到生产者发出脉冲,这在 Jon 的情况下经常发生

消费者线程并不自私。如果它不能做任何事情,它会让生产者线程玩球。然后生产者线程只玩球的时间足够长,可以在球上贴上它想要展示给消费者的标签。它对消费者大喊大叫,说“嘿,看看这个贴纸”,然后从球上跑开,这样消费者就可以看一眼,然后把贴纸从球上撕下来。冲洗并重复(球上现在可能有细菌;))。

于 2013-11-08T00:21:26.367 回答