3

私はこのように見えるシングルトンクラスを持っています、

public class CfgHandler
{
    private static readonly string ConfigDir = "Config";

    public T Get<T>() where T : class, new()
    {
        string cfgFile = Path.Combine(ConfigDir, typeof(T).FullName + ".json");

        if (File.Exists(cfgFile))
        {
            var reader = new JsonReader();
            return reader.Read<T>(File.ReadAllText(cfgFile));
        }

        return null;
    }

    public void Set<T>(T instance) where T : class, new()
    {
        string cfgFile = Path.Combine(ConfigDir, typeof(T).FullName + ".json");

        var writer = new JsonWriter();
        string json = writer.Write(instance);

        File.WriteAllText(cfgFile, json);
    }
}

このクラスはマルチスレッド環境で使用されており、ロックを追加したいと思います。cfg.Set<Foo>();ただし、クラス全体で1つのロックではありません。これは、との間で競合状態が発生したくないためですcfg.Set<Bar>()

次のクラスをに追加することを考えましたCfgHandler

private static class Locks<T>
{
    private static object _lock = new object();
    public static object Lock { get { return _lock; } }
}

次に、このようにロックします(GetとSetの両方)。

public void Set<T>(T instance) where T : class, new()
{
    lock(Locks<T>.Lock)
    {
        // save to disk
    }
}

些細なことを見逃していますか?私の目標を達成するためのより良い方法はありますか?

4

2 に答える 2

5

インスタンスごとにロックしますか、それともタイプごとにロックしますか?

(staticを使用して)それを行う方法は、CfgHandlerの異なるインスタンス上でさえLocks<T>.Lockすべての呼び出しが同じロックを共有することを意味します。Set<Foo>それはあなたが望むものですか?インスタンスごとにロックする方がよいと思います。これにより、の複雑さが軽減されますLocks<T>。プライベートインスタンスメンバーを宣言して(private object _lock = new object();)、それを使用するだけです(lock(this._lock)

編集シングルトンインスタンスを使用していて、CfgHandlerタイプごとにロックしたい場合は、アプローチは完全に問題ないと思います。単一のインスタンスを使用していないが、タイプごとにロックしたい場合は、Locks<T>静的にするのではなく、インスタンスを使用するようにしてください。

于 2012-04-26T13:31:42.837 に答える
2

詳細については、こちらの質問を参照してください。ジェネリッククラスの静的メンバーは型間で共有されていますか

あなたが持っている実装は単純ですが効果的です、それはSet<T>(T Instance)呼び出しへの同時アクセスを正しく防ぎます。私の唯一のアドバイスは、このAPIを同時に多数呼び出す場合は、ロック期間を制限する必要があるということです。たとえば、すべての作業を実行できますが、呼び出しをロックするwriter.write(instance)だけです。これは、呼び出しで実行しているように見える唯一の非スレッドセーフな作業です。

余談ですが、Get呼び出しでコードを改善する可能性があるので、ここで私の答えを参照してください。ファイルが使用されているかどうかを確認する方法はありますか?既存のファイルのチェックに関して。

于 2012-04-26T13:34:06.003 に答える