在访问集合的简单属性时,锁定是否有任何好处或危害,特别是.Count
? (这是可取的,不可取的,或者丝毫没关系?)(当然我需要将其锁定在任何写入或读取上)
private Dictionary<string, bool> database = new Dictionary<string, bool>();
private object databaseLock = new object();
public int Count
{
get
{
lock (databaseLock)
{
return database.Count;
}
}
}
就我个人而言,我认为这可能是明智之举,只是为了敲定约会需要锁定对字典的访问,而不是出于任何实际原因[*]。此外,在您访问的任何属性中,可能会有超过一个操作的操作。
[*]知道在C#中的(大多数)集合中Count
是一个由它维护的整数,所以应该始终是一个原子操作
答案 0 :(得分:4)
是的,在并发写入的情况下需要锁定,因为Dictionary
的文档不能保证这是安全的。你不能假设它的内部结构。
此规则的例外情况需要极端情况。
TL; DR:仅依靠记录在案的行为,否则你最终会陷入一个受伤的世界。
答案 1 :(得分:2)
这种代码大部分属于“伤害”类别。非常严重的伤害。锁只是不保护任何东西。在属性getter退出锁定后的一纳秒内,没有任何东西阻止线程在字典中添加或删除项目。这使得Count值只返回垃圾。获得值时,您不知道字典中有多少项。到目前为止,这个错误最有害的方面是通常正确。
此代码将保证您创建了一个线程竞赛,这是迄今为止最严重的诊断错误。
答案 2 :(得分:1)
编辑:正如我们在answer Dictonary.Count
中指出的那样,它不是线程安全的。 documentation说:
枚举集合本质上不是线程安全的 程序。在极少数情况下,枚举与写入竞争 访问时,必须在整个枚举期间锁定集合。
这意味着需要同步 。请注意,可能正在修改集合的任何其他代码都需要使用相同的锁。这非常容易出错,如果多个线程使用Dictionary,请考虑使用ConcurrentDictionary而不是