我有一个实现async
方法的多线程应用程序。该应用程序利用非线程安全的资源,并且需要在单个线程上使用。工作线程像这样被保护
private void EnsureWorkerIsRunning()
{
// first try without lock
if (_processingRequests)
{
return;
}
lock (_processLock)
{
// try again without lock
if (_processingRequests)
{
return;
}
_processingRequests = true;
DoWork();
_processingRequests = false;
}
}
那是
bool
)_processingRequests
是否true
没有任何锁定。如果正在处理请求,请返回并确信工作人员正在运行。_processingRequests
为false
,请继续执行lock
语句,一次只允许一个帖子输入。进入块集的第一个线程_processingRequests
到true
并启动工作线程。任何进入lock
块的后续线程都会保释,因为_processingRequests
现在是true
。直接添加lock
会导致无法接受的性能损失。
我正在寻找一种更优雅的方式来实现同样的目标,而不会影响性能。有什么想法吗?
答案 0 :(得分:1)
bool _processingRequests
的 lock(_processLock)
是无意义的。
使用适当的同步,例如Monitor
:
object _processLock = new object();
// acquiring lock,
if(Monitor.TryEnter(_processLock)) // if already acquired - exit immediately(return false)
try
{
...
}
finally { Monitor.Exit(_processLock); }
这可以做好工作,或者如果_processLock
已经被占用,就不要做(似乎你想要这种行为),不需要检查任何事情。
答案 1 :(得分:1)
您正在使用的技术称为Double-checked locking,在适当的情况下使用非常精细。它被广泛使用,它与优雅无关,因为它的主要目的是在每次输入lock
语句时减少性能下降,并额外检查没有锁定的条件。
但是在您的特定情况下,更适合仅使用Monitor.TryEnter
,如果某个线程已经获得锁定,则返回false
。
此外,blog post关于处理器上下文切换的影响,双重检查锁定避免了不必要的地方。