I have a singleton class which looks a lot like this,
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);
}
}
The class is used in a multithreaded environment and I want to add locks. But not one lock for the whole class, since I don’t want a race condition between cfg.Set<Foo>(); and cfg.Set<Bar>() as they work with different data.
I’ve thought about adding the following class to CfgHandler,
private static class Locks<T>
{
private static object _lock = new object();
public static object Lock { get { return _lock; } }
}
and then lock like this (both for Get and Set),
public void Set<T>(T instance) where T : class, new()
{
lock(Locks<T>.Lock)
{
// save to disk
}
}
Am I missing something trivial? Is there a better way of achieving my goal?
Lock per instance or lock per type?
The way you are doing it (with a static
Locks<T>.Lock) means that every call toSet<Foo>even on a different instance of CfgHandler will share the same lock. Is that what you want? I’m guessing you may be better off just locking per instance – it will save you the complexity ofLocks<T>. Just declare a private instance member (private object _lock = new object();) and use it (lock(this._lock))EDIT If you’re using a singleton instance of
CfgHandlerand want to lock per type, then I guess your approach is perfectly fine. If you’re not using a single instance, but still want to lock per type then just make sure to use an instance ofLocks<T>instead of making it static.