Prevent two threads entering a code block with the same value
c#, locking, multithreading
Solution
I would use `Lazy<T>` here. Below code will lock the cache, put the `Lazy` into the cache and return immediately. Long-running-operation will be executed once in a thread safe manner.
new Thread(() => Console.WriteLine("1-" + GetCachedValue("1").Value)).Start();
new Thread(() => Console.WriteLine("2-" + GetCachedValue("1").Value)).Start();
Lazy<object> GetCachedValue(string id)
{
lock (Cache)
{
if (!Cache.ContainsKey(id))
{
Lazy<object> lazy = new Lazy<object>(() =>
{
Console.WriteLine("**Long Running Job**");
Thread.Sleep(3000);
return int.Parse(id);
},
true);
Cache.Add(id, lazy);
Console.WriteLine("added to cache");
}
return Cache[id];
}
}
Problem
Say I have this function (assume I'm accessing Cache in a threadsafe way): ``` object GetCachedValue(string id) { if (!Cache.ContainsKey(id)) { //long running operation to fetch the value for id object value = GetTheValueForId(id); Cache.Add(id, value); } return Cache[id]; } ``` I want to prevent two threads from running the "long running operation" at the same time for the same value. Obviously I can wrap the whole thing in a lock(), but then the whole function would block regardless of value and I want two threads to be able to perform the long running operation as long as they're looking for different id's. Is there a built-in locking mechanism to lock based on a value so one thread can block while the other thread completes the long running operation so I don't need to do it twice (or N times)? Ideally as long as the long running operation is being performed in one thread, no other thread should be able to do it for the same id value. I could roll my own by putting the id's in a HashSet and then removing them once the operation completes, but that seems like a hack.