【发布时间】:2012-10-09 17:01:31
【问题描述】:
我需要根据一组有限的字符串在一个区域中创建一个关键部分。我希望为同一个字符串实例共享锁(有点类似于String.Intern 方法)。
我正在考虑以下实现:
public class Foo
{
private readonly string _s;
private static readonly HashSet<string> _locks = new HashSet<string>();
public Foo(string s)
{
_s = s;
_locks.Add(s);
}
public void LockMethod()
{
lock(_locks.Single(l => l == _s))
{
...
}
}
}
这种方法有什么问题吗?以这种方式锁定字符串对象是否可以,使用HashSet<string>时是否存在线程安全问题?
例如,创建一个Dictionary<string, object> 为每个字符串实例创建一个新的锁对象会更好吗?
最终实现
根据我采用以下实现的建议:
public class Foo
{
private readonly string _s;
private static readonly ConcurrentDictionary<string, object> _locks = new ConcurrentDictionary<string, object>();
public Foo(string s)
{
_s = s;
}
public void LockMethod()
{
lock(_locks.GetOrAdd(_s, _ => new object()))
{
...
}
}
}
【问题讨论】:
-
我在我的回答 here 中指出了使用
string作为锁定目标的一些怪癖。 -
我可以建议稍微改变一下吗? lock(_locks.GetOrAdd(_s, s => new object())) 这样一来,您只需为每个字符串创建一个对象,而不是每次调用 LockMethod() 时都创建一个。
-
关于JonSkeet 和BrianGideon 都提到的不相等字符串实例的问题,我建议使用
lock(_locks.GetOrAdd(String.Intern(_s), s => new object())),虽然实习可能仍然通过CompilationRelaxations.NoStringInterning关闭,然后这赢了也不行。也许,使用字符串的hashcode作为字典中的键会有所帮助?! -
@Oliver 实习在您锁定字符串时会出现问题(其他人可以锁定相同的实习字符串实例)。这里我们锁定一个新的对象实例,而不是字符串实例。没有其他人可以访问这个新对象实例。
-
如何安全删除keyed lock对象?
标签: c# .net multithreading .net-4.0 locking