是否可以使用Hashtable作为锁定对象?

oha*_*nho 3 .net c# multithreading

我有以下代码,其中"_ht"是表示缓存的Hashtable,"_ isLoaded"表示它是否已加载.

我们的系统有许多进程访问"_ht"对象,我需要它们等待它没有加载.

使用"_ht"作为锁定对象是错误的吗?我应该为此方案使用专用的对象类型类成员吗?

重要的是要提到这个班级是SINGLETON.

private Hashtable _ht = new Hashtable();
private bool _isLoaded = false;

internal Hashtable GetHT()
        {
            if (_isLoaded == false)
            {
                lock (_ht)
                {
                    if (_isLoaded == false)
                    {
                        LoadHt(_ht);
                    }
                }
            }

            return _ht;
        }
Run Code Online (Sandbox Code Playgroud)

Pet*_*iho 10

您当然可以锁定Hashtable对象,就像您可以在lock语句中使用.NET中的任何引用类型实例一样.但是,它通常被认为是一种较差的方法,主要是因为当一个或多个锁定对象可用于代码的其他部分时,很难跟踪代码如何使用锁定,他们也可能将其用于锁定(再次,不可思议,但你会惊讶于人们有时写的代码).

通常,对于锁定,优选单独的锁定对象.我会注意到在你的代码示例中,_ht应该是readonly,如果你添加一个单独的锁定对象(例如lockObj),那也应该是readonly.

也就是说,单身场景不应该以这种方式实现.相反,您应该使用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;
}
Run Code Online (Sandbox Code Playgroud)

要么:

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;
}
Run Code Online (Sandbox Code Playgroud)

当你有可能被访问的类型的其他成员时,后者很有用,但是你想确保哈希表的初始化尽可能延迟(例如,如果可能没有代码实际访问它,那么你可以避免完全初始化它).

(我改变了所有内容,static因为你将你的场景描述为一个单例,在这种情况下,只有static成员对代码示例有意义).

最后我会注意到这Hashtable堂课非常过时了.作为一个非泛型类,您真的应该认真考虑升级代码以使用现在已经十年的泛型类型.该Dictionary<TKey, TValue>班是最直接的替代品,但人们有时用Hashtable一个简单的设置,为此,HashSet<T>数据结构会更合适.