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.

Original source