一个优雅的Lock方案
虽然复杂,但是考虑到业务逻辑的需要,这套Lock方案还是相当不错的:
1: CacheItem cacheItemBeforeLock = null;
2: bool lockWasSuccessful = false;
3:
4: do
5: {
6: lock (inMemoryCache.SyncRoot)
7: {
8: if (inMemoryCache.Contains(key) == false)
9: {
10: cacheItemBeforeLock = new CacheItem(key, addInProgressFlag, CacheItemPriority.NotRemovable, null);
11: inMemoryCache[key] = cacheItemBeforeLock;
12: }
13: else
14: {
15: cacheItemBeforeLock = (CacheItem)inMemoryCache[key];
16: }
17:
18: lockWasSuccessful = Monitor.TryEnter(cacheItemBeforeLock);
19: }
20:
21: if (lockWasSuccessful == false)
22: {
23: Thread.Sleep(0);
24: }
25: } while (lockWasSuccessful == false);
26:
27: try
28: {
29: cacheItemBeforeLock.TouchedByUserAction(true);
30:
31: CacheItem newCacheItem = new CacheItem(key, value, scavengingPriority, refreshAction, expirations);
32: try
33: {
34: backingStore.Add(newCacheItem);
35: cacheItemBeforeLock.Replace(value, refreshAction, scavengingPriority, expirations);
36: inMemoryCache[key] = cacheItemBeforeLock;
37: }
38: catch
39: {
40: backingStore.Remove(key);
41: inMemoryCache.Remove(key);
42: throw;
43: }
44:
45: if (scavengingPolicy.IsScavengingNeeded(inMemoryCache.Count))
46: {
47: cacheScavenger.StartScavenging();
48: }
49:
50: instrumentationProvider.FireCacheUpdated(1, inMemoryCache.Count);
51: }
52: finally
53: {
54: Monitor.Exit(cacheItemBeforeLock);
55: }