1

I have some code that access a dictionary that I want to periodically refresh the contents of. The containing object is shared between several threads.

I dont know much about lock but in my head I imagine two thread hitting it, the first runs to completion before the next ones. This seems like a rather bad thing to happen if the body of the lock updated a shared value as the first thread one update it and then all pending threads would then do the same. This is my understanding of how it work.

So its a bit scenario dependent but in my case I came up with this

if (DateTimeOffset.Now.Subtract(_lastResolve) > TimeSpan.FromMinutes(2))
            {
                var copy = _configCache;
                lock (_lock)
                {
                    if (copy == _configCache)
                    {
                        var t = ResolveSettings();
                        t.Wait();
                        _configCache = t.Result;
                    }
                }
            }

return _configCache;

So before the lock it creates a ref copy of the dictionary we're updating and upon entering the lock body confirms that copy ref is still targeting the same dictionary.

So my question is two fold, is my understanding of lock behaviour correct and secondly is my approach to handling this particular problem sound?

Thanks

Sam
  • 1,725
  • 1
  • 17
  • 28

1 Answers1

2

This is called double-checked locking, which is explained e. g. on MSDN or SO with the singleton pattern.

To get something more compatible to the quoted code, you might have checked _lastResolve again in the locks body. But as datetime operations are rather costly, the assignment and check of a pointer might be a more lightweight way to accomplish what is required.

You should consider to declare _configCache as volatile to prevent the compiler from undesired optimization.

Hope this helps.

Community
  • 1
  • 1
Jürgen Röhr
  • 886
  • 6
  • 10