我正在使用C#中的简单锁定,使用lock
语句。有没有办法确定有多少其他线程正在等待在对象上获取锁定?我基本上想限制等待锁定的线程数量为5。如果第六个线程需要获取锁定,则我的代码将抛出异常。
我正在使用C#中的简单锁定,使用lock
语句。有没有办法确定有多少其他线程正在等待在对象上获取锁定?我基本上想限制等待锁定的线程数量为5。如果第六个线程需要获取锁定,则我的代码将抛出异常。
这可以通过Semaphore
类轻松实现,它将为您进行计数。请注意,在下面的代码中,我使用信号量对等待资源的线程数量进行非阻塞检查,然后我使用普通的lock
来序列化访问该资源。如果有超过5个线程等待资源,则会抛出异常。
public class YourResourceExecutor
{
private Semaphore m_Semaphore = new Semaphore(5, 5);
public void Execute()
{
bool acquired = false;
try
{
acquired = m_Semaphore.WaitOne(0);
if (!acquired)
{
throw new InvalidOperationException();
}
lock (m_Semaphore)
{
// Use the resource here.
}
}
finally
{
if (acquired) m_Semaphore.Release();
}
}
}
有一个显著的变体模式。您可以将方法名称更改为TryExecute
,并使其返回bool
而不是抛出异常。这完全取决于您。
请记住,在锁表达式中使用的对象不是锁的主题。它仅用作代码同步块的标识符。使用相同对象获取锁的任何代码块都将有效地被序列化。被“锁定”的是代码块,而不是在lock
表达式中使用的对象。
Semaphore
上使用“锁”不会以任何方式影响Semaphore
的行为。 - Brian Gideonlock
表达式中使用的对象并不是锁的主体。它仅仅作为代码同步块的标识符。任何使用相同对象获取锁的代码块将被有效地串行化。被“锁定”的是代码块,而不是lock
表达式中使用的对象。 - Brian GideonSemaphoreSlim
可以完美地工作……实际上可能更好。 - Brian Gideon您可以使用一个简单的共享计数器(整数),在锁定语句之前递增。如果该值等于5,则使您的线程避免锁定语句。然而,挑战在于您需要锁定计数器以确保递增操作是原子的。