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>();cfg.Set<Bar>()因为它们处理不同的数据。

我考虑过将以下课程添加到CfgHandler

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

然后像这样锁定(用于获取和设置),

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

我错过了一些微不足道的事情吗?有没有更好的方法来实现我的目标?

4

2 回答 2

5

每个实例锁定还是每个类型锁定?

您这样做的方式(使用 static Locks<T>.Lock)意味着Set<Foo>即使在 CfgHandler 的不同实例上的每个调用都将共享相同的锁。那是你要的吗?我猜你最好只锁定每个实例 - 它会为你节省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 回答