我正在审查一本书中的示例代码,并偶然发现了以下代码(简化)。在代码中,当调用Subscribe(T subscriber)时,线程进入锁部分。然后,当锁中的代码调用AddToSubscribers(T subscriber)方法时,该方法有另一个锁。为什么第二个锁是必要的?
public abstract class SubscriptionManager<T> where T : class
{
private static List<T> subscribers;
private static void AddToSubscribers(T subscriber)
{
lock (typeof(SubscriptionManager<T>))
{
if (subscribers.Contains(subscriber))
return;
subscribers.Add(subscriber);
}
}
public void Subscribe(T subscriber)
{
lock (typeof(SubscriptionManager<T>))
{
AddToSubscribers(subscriber);
}
}
}发布于 2011-12-21 15:08:43
在这种情况下,它不是;但是,由于锁是可重入的,这对于确保AddToSubscribers的任何其他调用者都能观察到锁很有用。实际上,出于这个原因,我会说“把它从Subscribe中删除,让AddToSubscribers来做锁定”。
然而!锁定Type是非常危险的。字段会更安全:
// assuming static is correct
private static readonly object syncLock = new object();和lock(syncLock)。根据分配subscribers的时间不同,您也可以使用lock(subscribers) (而不是额外的字段)。
我还应该注意到,将实例方法添加到静态状态是非常好的……不寻常;IMO Subscribe应该是一个static方法,因为它与当前实例无关。
发布于 2011-12-21 15:08:50
在您发布的代码中,这不是必需的。但话又说回来,您发布的代码是不完整的-例如,订阅者列表从未初始化。
锁定typeof(SubscriptionManager)可能也不是一个好主意--锁定subscribers字段会更好--但需要初始化subscribers字段,例如
private static List<T> subscribers = new List<T>();发布于 2011-12-21 15:09:33
您可能应该阅读该示例附近的内容,看看书中谈到了什么。
对于这种特殊情况-不,第二个锁是不必要的。
注意:该示例是危险的,因为它锁定在公共对象(type)上。通常情况下,一个锁在特殊的私有对象上,所以外部代码不会因为错误地锁在同一个对象上而错误地引入死锁。
https://stackoverflow.com/questions/8586150
复制相似问题