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

时间:2012-04-21 17:04:33

标签: c# concurrency static locking initialization

我对静态类的静态成员的初始化有问题。据我所知,它只会被初始化一次,所以当我在并发中执行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,180】【主题12】  _lockAdd的哈希码(51755728)...

【信息】【2012-04-20 15:26:58,624】【thread16】  _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(...)
                }
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

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

private static readonly object _lockAdd = new object();

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

答案 1 :(得分:0)

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