gpt4 book ai didi

c# - 有没有办法等待多个信号量

转载 作者:太空狗 更新时间:2023-10-30 00:36:47 27 4
gpt4 key购买 nike

我正在尝试编写一个可以同时等待多个资源池的应用程序。每个资源池都由一个Semaphor 控制。我可以在传递整个信号量列表的地方使用 WaitHandle.WaitAll() 吗?此实现是否存在潜在的死锁问题?

我当前的实现:

namespace XXX
{
using System.Collections.Generic;
using System.Linq;
using System.Threading;

public class ResourcePoolManager
{
private readonly IDictionary<string, Semaphore> resourcePools = new Dictionary<string, Semaphore>();

public void AddResourcePool(string resourceName, int maxConcurrentConsumers)
{
this.resourcePools.Add(resourceName, new Semaphore(maxConcurrentConsumers, maxConcurrentConsumers));
}

public void RequestResource(string resourceName)
{
this.resourcePools[resourceName].WaitOne();
}

public void RequestMultipleResources(string[] resourceNames)
{
Semaphore[] resources = resourceNames.Select(s => this.resourcePools[s]).ToArray();

WaitHandle.WaitAll(resources);
}

public void ReleaseResource(string resourceName)
{
this.resourcePools[resourceName].Release(1);
}
}
}

最佳答案

当然,您可以使用它,但它只会在所有信号量同时触发时触发。根据应用程序其余部分的结构,可能确实存在饥饿问题。例如,如果您有两个资源 A 和 B,以及三个线程:

  1. 继续获取资源A,使用它一秒钟,然后释放它并循环
  2. 继续获取资源B,使用它一秒钟,然后释放它并循环
  3. 等待 A 和 B 都可用

您可以很容易地等待 A 和 B 同时可用。

根据您的应用程序,简单地按顺序获取每个信号量可能会更好,这样可以避免这种饥饿问题,但会引入传统的死锁问题。但是,如果您确定这些锁在大多数时间都可用,那么它可能是安全的(但也可能是一个定时炸弹,只是在等待您的应用程序处于实际负载下...)

根据您的示例代码,另一种选择是对信号量创建全局排序 - 例如,按名称排序 - 并始终确保按该顺序获取它们。如果这样做,您可以通过按升序逐个锁定每个信号量来简单地执行多重锁定。

在这种情况下,释放顺序并不严格——但如果你乱序释放,你应该在你刚刚释放的锁“之后”释放所有锁,然后再获取任何锁(这是一个经验法则应该给你死锁安全。有可能通过详分割析进一步放松)。推荐的方法是尽可能以获取的相反顺序发布,在这种情况下,您可以随时将其转化为进一步的获取。例如:

  1. 获取锁A
  2. 获取锁B
  3. 获取锁C
  4. 释放锁C
  5. 获取锁D
  6. 释放 B(现在在释放 D 之前不要获得任何东西!)
  7. 版本 D
  8. 获得E
  9. 版本 E
  10. 版本 A

只要一切都遵循这些规则,就不会出现死锁,因为不会形成等待者的循环。

这种方法的缺点是它可能会在等待另一个线程时持有锁,从而延迟其他线程。这不会永远持续下去;在上面的三个线程的例子中,我们可能会遇到这样的场景:

  1. 开始时,线程 2 持有 B。线程 1 持有 A。
  2. 在 A 上线程 3 个 block 。
  3. (时间流逝)
  4. 线程 1 发布 A。
  5. 线程 3 锁定 A,阻塞 B。
  6. 线程 1 在 A 上阻塞。
  7. (时间流逝)
  8. Thread 2 发布 B。
  9. 线程 3 锁定 B,工作,然后解锁。
  10. 线程 1 锁定 A,取得进展。

如您所见,有一些停机时间,线程 1 在 A 上被阻塞,即使没有真正的工作要做。但是,通过这样做,我们大大提高了线程 3 取得进展的机会。

这是否是一个好的权衡取决于您的应用程序 - 如果您可以明确地说多个线程永远不会进入锁,它甚至可能无关紧要。但是没有一种正确的方法:)

关于c# - 有没有办法等待多个信号量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/826769/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com