空锁语句¶
ID: cs/empty-lock-statement
Kind: problem
Security severity:
Severity: warning
Precision: high
Tags:
- changeability
- readability
- concurrency
- language-features
- external/cwe/cwe-585
Query suites:
- csharp-security-and-quality.qls
空锁语句会暂停执行,直到可以获取锁,然后立即释放该锁。这有时可以达到预期的效果,但通常可以使用事件等待句柄以更好的方式实现相同的结果。
代码中出现空锁语句还有其他原因。例如,该语句最初可能包含后来被删除的代码,或者代码可能被意外放置在语句之外,而它应该位于语句内部。
建议¶
由于空锁语句有多种原因,因此处理空锁语句需要仔细分析并充分了解代码的预期目标。在某些情况下,可以通过重构代码以使用更合适的同步机制来解决问题。在其他情况下,锁是冗余的,可以完全删除。在最常见的情况下,空锁可能只是表示代码同步不正确,需要修复或重新设计。
示例¶
在下面的代码中,使用了一个空锁语句来确保在方法 Y
打印 value
之前已完成对它的赋值。
class EmptyLockStatement
{
private static readonly object locker = new object();
private static Thread threadX;
private static Thread threadY;
private static int value;
static void Main(string[] args)
{
threadX = new Thread(X);
threadY = new Thread(Y);
threadX.Start();
threadX.Join();
while (threadY.ThreadState == ThreadState.Unstarted) ;
threadY.Join();
}
static void X()
{
lock (locker)
{
threadY.Start();
value = 1;
}
}
static void Y()
{
lock (locker) { }
Console.WriteLine(value);
}
}
前面的示例有效,但可以使用事件等待句柄以更好、更惯用的方式实现。
class EmptyLockStatementFix
{
private static Thread threadX;
private static Thread threadY;
private static int value;
private static EventWaitHandle waitHandle = new AutoResetEvent(false);
static void Main(string[] args)
{
threadX = new Thread(X);
threadY = new Thread(Y);
threadX.Start();
threadX.Join();
while (threadY.ThreadState == ThreadState.Unstarted) ;
threadY.Join();
}
static void X()
{
threadY.Start();
value = 1;
waitHandle.Set();
}
static void Y()
{
waitHandle.WaitOne();
Console.WriteLine(value);
}
}