为什么C#中没有获取多个信号量许可的方法?我想这样使用我的信号量:
semaphore.Acquire(2);
semaphore.Acquire(2);
WaitOne()
获取信号量。就像您在所有同步类上所做的那样。Aquire(n)
方法将高居该清单之首。这是一种非常麻烦的方法,Windows上的底层本地实现也不支持它。这会产生导致死锁的严重风险,几乎无法进行调试,代码将挂起在一个循环中的不可见方法内,深埋在CLR中。这增加了等待时需要终止代码时候的语义,这些语义对于需要被中止的代码非常重要。您可以自己循环,这是一个简单的解决方法并且在调试死锁时易于查看,因此您可以至少检查计数器。public static bool Acquire (this Semaphore semaphore, int permits) {
for (int i = 0; i < permits; i++) {
/*
* If millisecondsTimeout is zero, the method does not block.
* It tests the state of the wait handle and returns immediately.
*/
if (!semaphore.WaitOne (0)) {
semaphore.Release (i);
return false;
}
}
return true;
}
您可以编写自己的扩展方法到Semaphore类中:
namespace Extentions
{
public static class SemaphoreExtentions
{
public static void Acquire(this Semaphore semaphore, int permits)
{
for (int i = 0; i < permits; ++i)
semaphore.WaitOne();
}
}
}
使用方法:
using Extentions;
//...
public void SomeMethod()
{
var sem = new Semaphore(10, 10);
sem.Acquire(6);
}
public static void Acquire(this Semaphore semaphore, int permits)
{
lock (semaphore)
{
for (int i = 0; i < permits; ++i)
semaphore.WaitOne();
}
}
lock (semaphore)
不是一个好主意。需要一个锁对象,只能由试图获取给定信号量的调用者锁定,例如 readonly object acquireLock = new object();
... lock (acquireLock) ...
原因:Acquire
可以持有这个锁很长时间,因为它积累了足够的许可。假设其他地方的代码希望为某些其他目的 lock (semaphore)
- 它将被卡在等待此代码上。不幸的是,传递一个 sync
对象可能会导致相反的问题:两个不同的调用者,对于相同的信号量具有不同的同步对象,可能会死锁。... - ToolmakerSteve