我不确定如何最好地解释我想要的东西,所以让我写一些说明性的代码。基本上:后台线程遍历大量工作,但在极少数情况下需要中断。
// This loop runs in a long-running thread that does
// a lot of high-priority work on a shared resource.
// The vast majority of time it is the only thread accessing the resource.
private void FastLoop()
{
lock (locker)
{
while (true)
{
DoWork();
// Somehow checking if another thread needs the shared resource.
// Ideally I'd like something like this,
// but alas: Monitor.BlockedCount() doesn't exist.
while (Monitor.BlockedCount(locker) > 0)
Monitor.Wait(locker);
}
}
}
// Methods like this get called rarely, but there is many of them
// so the code required to lock and unlock from secondary threads
// should be simple.
private void OtherThreads()
{
lock (locker)
{
DoSomethingElse();
Monitor.Pulse(locker);
}
}
当前实现使用最简单的方法,基本上只是快速解锁并再次锁定,以便为其他线程提供跳入的机会。
private void FastLoopCurrentImplementation()
{
while (true)
{
lock (locker)
DoWork();
}
}
private void OtherThreadsCurrentImplementation()
{
lock (locker)
DoSomethingElse();
}
有些东西告诉我这种简单化的方法可能会有问题。如果我没有弄错的话,即使另一个线程被阻止,循环也可以解锁并立即再次锁定。这意味着其他方法可能会花费多个主线程循环周期。
我认为这种方法不理想吗?什么是锁定/解锁的首选方法?
答案 0 :(得分:1)
您可以自己统计阻止的线程:
private long blockedCount = 0;
private void FastLoop()
{
lock (locker)
{
while (true)
{
DoWork();
while (Interlocked.Read(ref blockedCount) > 0)
Monitor.Wait(locker);
}
}
}
private void OtherThreads()
{
try
{
var wasBlocked = false;
if (!Monitor.TryEnter(locker))
{
wasBlocked = true;
Interlocked.Increment(ref blockedCount);
Monitor.Enter(locker);
}
DoSomethingElse();
if (wasBlocked)
Interlocked.Decrement(ref blockedCount);
Monitor.Pulse(locker);
}
finally
{
Monitor.Exit(locker);
}
}