【发布时间】:2011-10-08 19:48:25
【问题描述】:
我在前几天发布的评论中对此感到有些悲伤,所以我想发布这个问题,试图让人们告诉我我疯了,我会接受,或者告诉我我可能是对的,我也很乐意接受。我也可以接受介于两者之间的任何东西。
假设您有一个非线程安全的对象类型,例如Dictionary<int, string>。为了争论,我知道你也可以使用线程安全的ConcurrentDictionary<int, string>,但我想谈谈多线程环境中非线程安全对象的一般做法。
考虑以下示例:
private static readonly Dictionary<int, string> SomeDictionary = new Dictionary<int, string>();
private static readonly object LockObj = new object();
public static string GetById(int id)
{
string result;
/** Lock Bypass **/
if (SomeDictionary.TryGetValue(id, out result)
{
return result;
}
lock (LockObj)
{
if (SomeDictionary.TryGetValue(id, out result)
{
return result;
}
SomeDictionary.Add(id, result = GetSomeString());
}
return result;
}
锁定模式称为Double-Checked Locking,因为如果字典已使用该ID 初始化,则会主动绕过锁定。字典的“Add”方法是在锁内调用的,因为我们只想调用该方法一次,因为如果你尝试用相同的键添加一个项目,它会抛出异常。
据我了解,这种锁定模式本质上同步了 Dictionary 的处理方式,这使其成为线程安全的。但是,我得到了一些负面评价,认为这实际上并不能保证线程安全。
那么,我的问题是,这种锁定模式对于多线程环境中的非线程安全对象是否可以接受?如果不是,那么使用什么模式会更好? (假设没有相同的 C# 类型是线程安全的)
【问题讨论】:
-
简短的回答是您无法安全地执行此操作,详情请参阅副本。
标签: c# multithreading locking thread-safety