不一致的锁顺序¶
ID: cs/inconsistent-lock-sequence
Kind: problem
Security severity:
Severity: error
Precision: high
Tags:
- reliability
- correctness
- concurrency
- external/cwe/cwe-662
Query suites:
- csharp-security-and-quality.qls
应以一致的顺序锁定并发持有的锁,否则程序可能会死锁。此规则检测嵌套的 lock
语句,这些语句在程序的不同部分以不同的顺序锁定变量。
建议¶
可以通过确保嵌套的 lock
语句始终以相同的顺序锁定变量来避免此问题。
示例¶
以下示例显示了一个运行两个线程的程序,该程序由于 thread1
持有 lock1
并等待获取 lock2
而死锁,而 thread2
持有 lock2
并等待获取 lock1
。
using System;
using System.Threading;
class Deadlock
{
private readonly Object lock1 = new Object();
private readonly Object lock2 = new Object();
public void thread1()
{
lock (lock1)
{
Console.Out.WriteLine("Thread 1 acquired lock1");
Thread.Sleep(10);
Console.Out.WriteLine("Thread 1 waiting on lock2");
lock (lock2) // Deadlock here
{
}
}
}
public void thread2()
{
lock (lock2)
{
Console.Out.WriteLine("Thread 2 acquired lock2");
Thread.Sleep(10);
Console.Out.WriteLine("Thread 2 waiting on lock1");
lock (lock1) // Deadlock here
{
}
}
}
}
通过如下所示对 lock
变量重新排序,可以解决此问题。
using System;
using System.Threading;
class DeadlockFixed
{
private readonly Object lock1 = new Object();
private readonly Object lock2 = new Object();
public void thread1()
{
lock (lock1)
{
Console.Out.WriteLine("Thread 1 acquired lock1");
Thread.Sleep(10);
Console.Out.WriteLine("Thread 1 waiting on lock2");
lock (lock2)
{
}
}
}
public void thread2()
{
lock (lock1) // Fixed
{
Console.Out.WriteLine("Thread 2 acquired lock1");
Thread.Sleep(10);
Console.Out.WriteLine("Thread 2 waiting on lock2");
lock (lock2) // Fixed
{
}
}
}
}
参考¶
MSDN,C# 参考:lock 语句。
CERT Oracle Java 编码标准:LCK07-J. 避免通过以相同的顺序请求和释放锁来避免死锁。
常见弱点枚举:CWE-662。