CodeQL 文档

等待期间持有锁

ID: cs/locked-wait
Kind: problem
Security severity: 
Severity: warning
Precision: high
Tags:
   - reliability
   - correctness
   - concurrency
   - external/cwe/cwe-662
   - external/cwe/cwe-833
Query suites:
   - csharp-security-and-quality.qls

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

在调用 System.Threading.Monitor.Wait() 期间持有锁会导致性能问题或死锁,因为该锁会阻止其他线程运行。这可能是由于将对 System.Threading.Monitor.Wait() 的调用嵌套在两个 lock 语句中,或者由于等待的对象与被锁定的对象不同而导致的。

同步方法(带有属性 [MethodImpl(MethodImplOptions.Synchronized)])也可能导致问题,因为它们等效于 lock(this)lock(typeof(Class))

建议

确保对 System.Threading.Monitor.Wait() 的调用发生在单个 lock 语句中,并确保 System.Threading.Monitor.Wait() 的参数与 lock 语句中的变量匹配。

示例

以下示例锁定两个变量,countLocktextLock,然后调用 System.Threading.Monitor.Wait()。但是,在 Wait() 的持续时间内,变量 countLock 被锁定,这会导致程序死锁。

class Message
{
    readonly Object countLock = new Object();
    readonly Object textLock = new Object();

    int count;
    string text;

    public void Print()
    {
        lock (countLock)
        {
            lock (textLock)
            {
                while (text == null)
                    System.Threading.Monitor.Wait(textLock);
                System.Console.Out.WriteLine(text + "=" + count);
            }
        }
    }

    public string Text
    {
        set
        {
            lock (countLock)
            {
                lock (textLock)
                {
                    ++count;
                    text = value;
                    System.Threading.Monitor.Pulse(textLock);
                }
            }
        }
    }
}

可以通过移动 lock 语句来解决此问题,以便在等待期间不会锁定 countLock

class Message
{
    readonly Object countLock = new Object();
    readonly Object textLock = new Object();

    int count;
    string text;

    public void Print()
    {
        lock (textLock)
        {
            while (text == null)
                System.Threading.Monitor.Wait(textLock);
            lock (countLock)
                System.Console.Out.WriteLine(text + "=" + count);
        }
    }

    public string Text
    {
        set
        {
            lock (countLock)
            {
                lock (textLock)
                {
                    ++count;
                    text = value;
                    System.Threading.Monitor.Pulse(textLock);
                }
            }
        }
    }
}

参考

  • ©GitHub 公司
  • 条款
  • 隐私