CodeQL 文档

空锁语句

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

点击查看 CodeQL 代码库中的查询

空锁语句会暂停执行,直到可以获取锁,然后立即释放该锁。这有时可以达到预期的效果,但通常可以使用事件等待句柄以更好的方式实现相同的结果。

代码中出现空锁语句还有其他原因。例如,该语句最初可能包含后来被删除的代码,或者代码可能被意外放置在语句之外,而它应该位于语句内部。

建议

由于空锁语句有多种原因,因此处理空锁语句需要仔细分析并充分了解代码的预期目标。在某些情况下,可以通过重构代码以使用更合适的同步机制来解决问题。在其他情况下,锁是冗余的,可以完全删除。在最常见的情况下,空锁可能只是表示代码同步不正确,需要修复或重新设计。

示例

在下面的代码中,使用了一个空锁语句来确保在方法 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);
    }
}
  • ©GitHub 公司
  • 条款
  • 隐私