views:

72

answers:

2

I am writing a system for automatically recalculating the results of costly methods, and then storing them in a cache. The cache may be distributed, meaning (obviously) multiple processes can access it.

On the first invocation of the method to cache the result for, I want to spawn a thread that will periodically recalculate the result of the method and update the cache.

I want only a single thread of execution to be spawned per cache item. In a multi-process environment, can this be achieved using a cross process mutex such as this?

http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx

Are there any pitfalls with this approach?

Edit:

Truth table for my implementation:

// in-cache | mutex-found
//   0            0      //not in cache, no mutex; start thread
//   1            0      //in cache, no mutex; assume thread already started (re-calculating thread could be in another process)
//   0            1      //not in cache, mutex found; thread started, do not start thread - log error (and possibly start new thread)
//   1            1      //in cache, mutex found; thread started, do not start thread
+2  A: 

In short, I believe that this is a good approach. The only pitfall is mutex identification - if at all possible, tell secondary threads about the mutex by its handle. If named mutexes must be used, you might want to name the mutex the same as your process UUID to promote uniqueness.

Reinderien
A: 

On second thought, there may be an easier way to do this. Given your description of the cache being "periodically recalculated", instead of having threads, you could just have a central System.Threading.Timer. Since it can only be associated with a single callback, there is no risk of multiple threads attempting to rewrite the cache. The only caveat is that this timer event would need to do a single write to the cache memory in an atomic fashion (without being interrupted by another thread in mid-write).

Reinderien
Is such a timer visible inter-process though?
Ben Aston
I think it wouldn't need to be: all you'd have is an inter-process boolean flag that signals that the timer has been instantiated by someone. Combining this with the previous solution, your inter-process objects could be the "timer allocated already" flag, and the mutex that's only taken while the cache is being rewritten, and the cache memory itself; the timer could be thread-local.
Reinderien
Is there a performance benefit to using the presence of a cache object as the timer already allocated flag, rather than solely relying on the mutex? I'm trying to understand your approach.
Ben Aston
If you were to solely rely on a mutex, would it be perpetually owned by the thread that rewrites the cache? If so, what's to stop other threads from interrupting that thread in the middle of a write, reading half new data and half old data?If you solely rely on the mutex and it's only owned while the cache is being rewritten, that could work, but then there's no way of knowing which thread will end up doing any given cache update.If you use the flag to indicate that the timer has been allocated, in conjunction with the mutex to indicate that the cache is being rewritten: both issues fixed.
Reinderien
My original idea was that the mutex *would* be perpetually owned by the thread that rewrites the cache. I make the assumption that the underlying cache (my targets are the ASP.NET data cache and Memcached) is thread-safe (i.e I don't have to worry about reads during writes and vice-versa). I read that these caching subsystems are threadsafe, so I presume I am safe in this assumption? I have updated my question with the truth table corresponding to the logic in my implementation.
Ben Aston
I'm not familiar with the caching libraries that you're using, but if it's safe to assume that they're thread-safe, then you can do away with the mutex and just have the boolean flag.
Reinderien