2012-05-23 61 views
10

我想實現一個通用的線程安全的高速緩存方法,我不知道我應該如何實現它的鎖。如何通過緩存鍵進行鎖定?

它應該是這個樣子:

//private static readonly lockObject = new Object(); 

public T GetCache<T>(string key, Func<T> valueFactory...) 
{ 

    // try to pull from cache here 

    lock (lockObject) // I don't want to use static object lock here because then every time a lock is performed, all cached objects in my site have to wait, regarding of the cache key. 
    { 
    // cache was empty before we got the lock, check again inside the lock 

    // cache is still empty, so retreive the value here 

    // store the value in the cache here 
    } 

    // return the cached value here 

} 
+0

你到底想達到什麼目的?在我看來,你是混淆類型的鎖2之間:鎖保證只有一個線程可以編輯緩存的對象,並鎖定,以確保添加/從緩存中刪除是線程安全的。爲每個對象添加一個鎖定將有助於確保只有一個線程可以更改它,但它與從緩存中添加/刪除它無關(這個實現你沒有提供,但我猜測它會是某種字典)。無論如何,我不認爲你可以解散緩存 - 收集級鎖。 – YavgenyP

+0

我正在使用Asp.net緩存...所以我不必實現自己的字典...而我正在談論鎖定添加...讓我們說1000人同時請求頁面,我想只有他們其中的緩存爲對象,和所有的其他人使用它... – Amir

+0

你仍然需要鎖定底層集合,而不是對象。如果我理解正確,你想要做的是檢查對象是否不存在於此集合中,然後才添加它。如果您使用.net 4,則可以使用其新的阻塞集合之一(例如ConcurrentDictionary)來確保每個鍵只添加一次。 – YavgenyP

回答

1

這樣的話,你使用mutex

public T GetCache<T>(string key, Func<T> valueFactory...) 
{ 
    // note here that I use the key as the name of the mutex 
    // also here you need to check that the key have no invalid charater 
    // to used as mutex name. 
    var mut = new Mutex(true, key); 

    try 
    { 
     // Wait until it is safe to enter. 
     mut.WaitOne(); 

     // here you create your cache 
    } 
    finally 
    { 
     // Release the Mutex. 
     mut.ReleaseMutex(); 
    } 
} 
+0

即使他需要的任何類型的鎖或同步對象 - 他爲什麼要使用互斥,而不是監管? 「Mutex類使用比Monitor類更多的系統資源」(來自[msdn](http://msdn.microsoft.com/en-us/library/hw29w7t1.aspx)) – YavgenyP

+1

@YavgenyP有兩個主要原因:1 )用於鎖定所有使用/製作此緩存的線程,並且只鎖定一個線程。 2)給名稱並僅鎖定緩存的相同部分,而不是每個請求的緩存。 - 現在,我不知道他是否需要同步,我會熱烈地回覆他,不要爭論他是否需要。 – Aristos

0

的.NET ConcurrentDictionary<TKey, TItem>實現了這個內部通過爲每個單獨的鎖密鑰哈希。這具有僅鎖定一個相關散列的好處,即使在處理項目添加和刪除時也是如此。

1

我剛剛發現LazyCache庫。儘管如此,我還沒有嘗試過它。

IAppCache cache = new CachingService(); 
ComplexObject cachedResults = cache.GetOrAdd("uniqueKey", 
    () => methodThatTakesTimeOrResources()); 
+0

感謝您的鏈接 - 我在生產中使用它,它運行良好,但我想說 - 我寫了它。 – alastairtree