你当然可以锁定Hashtable
对象,就像你可以在lock
语句中使用任何引用类型实例的.NET。然而,它通常被认为是一种劣质的方法,主要是因为当代码的其他部分有一个或多个锁对象可用时,他们很难跟踪代码如何使用锁定,他们也可能使用它来锁定再次,不可思议,但你会惊讶于人们写的代码)。
对于通常的锁定,单独的锁定对象是最好的。我会注意到在你的代码示例中,_ht
应该是readonly
,并且如果你添加一个单独的锁定对象(例如lockObj
),它也应该是只读的。
也就是说,单例情景不应该以这种方式实现。相反,您应该使用CLR自己的静态初始化,或Lazy<T>
类:
private static readonly Hashtable _ht = InitializeTable();
internal static Hashtable GetHT() { return _ht; }
private static Hashtable InitializeTable()
{
Hashtable table = new Hashtable();
LoadHt(table);
return table;
}
或者:
private static readonly Lazy<Hashtable> _ht = new Lazy<Hashtable>(() => InitializeTable());
internal static Hashtable GetHT() { return _ht.Value; }
private static Hashtable InitializeTable()
{
Hashtable table = new Hashtable();
LoadHt(table);
return table;
}
时,你有可能被访问的类型中的其他成员,后者是有用的,但是你想确保散列表的初始化尽可能延迟(例如,如果可能的话,没有代码实际上可以访问它,所以你可以避免初始化它)。
(我将所有内容都更改为static
,因为您将您的场景描述为单例,在这种情况下,只有static
成员对代码示例有意义)。
最后我会注意到Hashtable
这个类已经过时了。作为非泛型类,您应该认真考虑升级代码以使用现在十年的泛型类型。 Dictionary<TKey, TValue>
类是最直接的替代品,但人们有时使用Hashtable
作为一个简单集合,对此,数据结构更合适。
如果你想让我花费我的答案,为什么要使用锁对象说,所以我认为这是非常明显的,如果不是,那么你应该考虑它。反正lemme知道 – 2014-11-23 08:37:47
@ohadinho很多人说_usually_使用了一个单独的'object',但直到你锁定的对象是'private',而不是直接使用你的'Hashtable'没有任何错误(记住你正在锁定一个实例,而不是一个类,而且没有其他人知道该对象锁定它,所以它不是死锁的来源)。这就是说我会**这个代码全部放在一起,我会用'懒惰'。 –
2014-11-23 08:44:08
@AdrianoRepetti:请注意,仅仅因为_field_被声明为“private”,并不意味着该对象本身是私有的。实际上,在这个例子中,'Hashtable'对象实际上是通过'GetHT()'方法公开的(尽管只是'内部',但仍然在拥有类之外)。 – 2014-11-23 08:50:57