等待期间持有锁¶
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
在调用 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
语句中的变量匹配。
示例¶
以下示例锁定两个变量,countLock
和 textLock
,然后调用 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);
}
}
}
}
}