初始化静态类的静态成员时的奇怪行为

本文关键字:静态类 静态成员 初始化 | 更新日期: 2023-09-27 18:31:49

我在初始化静态类的静态成员时遇到问题。据我所知,它只会初始化一次,所以当我并发执行 fooList.Add(...) 时,我会锁定这个变量,以确保此操作是线程安全的:

internal static class ObjectA
{
    private static object _lockAdd = new object();
    public void functionA()
    {
       lock (_lockAdd)
       {...

我遇到了一些奇怪的情况,所以我决定用log4net编写_lockAdd的哈希码,令我惊讶的是,这就是我观察到的:

【信息】【

2012-04-20 15:26:44,080】【线程12】 _lockAdd的哈希码(51755728)...

【信息】【

2012-04-20 15:26:58,624】【线程16】 _lockAdd的哈希码(31071611)...

如您所见,两个"_lockAdd"地址是不同的,为什么会这样,还是我对静态成员的理解是错误的?当操作在静态类中时,我应该如何确保线程安全?

很抱歉假代码的错误,这是我的实际代码:

internal static class UtilExtension
{               
    private static object _lockAdd = new object(); //initial twice ? why?
    public static void DoAdd(this Type entityType)
    {            
        if (!Pools.Has(entityType))
        {
            lock (_lockAdd) 
            {
                if (!Pools.Has(entityType)) //insure operation below is thread safe
                {
                    // i find something wrong in concurrency,so i log the _lockAdd's hashcode,
                    // and then i found it's hashcode is different( in my opinion, it means not the same variables )
                    LogUtil.Info(_lockAdd.GetHashCode().ToString());
                    //... do fooList.Add(...)
                }
            }
        }
    }
}

初始化静态类的静态成员时的奇怪行为

对于仅用于lock ing的对象,请使用readonly

private static readonly object _lockAdd = new object();

如果对象以某种方式被覆盖,则下次启动应用程序时,编译器或运行时很可能会得到不同的结果。

也许我让它变得复杂,事实是,静态成员总是线程不安全的。因此,当我们使用静态成员(_lockAdd)作为锁定目标时,我们应该添加只读以确保_lockAdd仅启动一次。