字段上的无效同步¶
ID: cs/unsafe-sync-on-field
Kind: problem
Security severity:
Severity: error
Precision: high
Tags:
- reliability
- correctness
- concurrency
- external/cwe/cwe-662
- external/cwe/cwe-366
Query suites:
- csharp-security-and-quality.qls
锁定已修改字段的 lock
语句不太可能提供线程安全。这是因为不同的线程只锁定字段的值,而不锁定字段本身。由于字段的值会发生变化,因此不同的线程会锁定不同的对象,因此不是互斥的。
建议¶
不要锁定字段本身,而应使用专用对象进行锁定。该对象应为 private
和 readonly
,以确保无法在其他地方修改或锁定它。
示例¶
在以下示例中,可以在不同线程上同时调用方法 AddItem
。 AddItem
尝试使用 lock
语句保护字段 total
。但是,同时使用 AddItem
会导致 total
的值不正确。
class Adder
{
dynamic total = 0;
public void AddItem(int item)
{
lock (total) // Wrong
{
total = total + item;
}
}
}
以下代码通过使用专用对象 mutex
进行锁定来解决此问题。
using System;
class Adder
{
dynamic total = 0;
private readonly Object mutex = new Object();
public void AddItem(int item)
{
lock (mutex) // Fixed
{
total = total + item;
}
}
}