1

静的クラスの静的メンバーの初期化に問題があります。私の知る限り、初期化は 1 回だけなので、この操作がスレッド セーフであることを確認するために、同時実行で fooList.Add(...) を実行するときにこの変数をロックします。

internal static class ObjectA
{
    private static object _lockAdd = new object();

    public void functionA()
    {
       lock (_lockAdd)
       {...

私はいくつかの奇妙な状況に遭遇したので、log4net によって _lockAdd のハッシュコードを書くことにしました。驚いたことに、これは私が観察したものです:

【INFO】【2012-04-20 15:26:44,080】【thread12】_lockAddさんのハッシュコード(51755728)...

【INFO】【2012-04-20 15:26:58,624】【thread16】_lockAddのハッシュコード(31071611)...

ご覧のとおり、2 つの '_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(...)
                }
            }
        }
    }
}
4

2 に答える 2

1

lockingにのみ使用されるオブジェクトの場合は、次を使用しreadonlyます。

private static readonly object _lockAdd = new object();

オブジェクトが何らかの理由で上書きされていた場合、次にアプリケーションを起動したときに、コンパイラーまたはランタイムのいずれかから異なる結果が得られる可能性があります。

于 2012-04-21T17:38:10.687 に答える
0

複雑にするかもしれませんが、実際のところ、静的メンバーは常にスレッドセーフではありません。したがって、静的メンバー (_lockAdd) をロック ターゲットとして使用する場合は、readonly を追加して、_lockAdd が 1 回だけ初期化されるようにする必要があります。

于 2012-04-23T01:21:28.437 に答える