2010-05-29 51 views
0

我有一個自定義的Cache實現,它允許使用LRU(最近最少使用)緩存替換算法緩存TCacheable<TKey>後代。如何提高多線程訪問Cache(自定義實現)

每一個元件被訪問時,它被鼓入到使用以下同步功能的LRU隊列的頂部:

// a single instance is created to handle all TCacheable<T> elements 
public class Cache() 
{ 
    private TCacheable<T> oldest, newest; 

    private object syncQueue = new object(); 
    private void topQueue(TCacheable<T> el) 
    { 
     lock (syncQueue) 
     if (newest != el) 
     { 
      if (el.elder != null) el.elder.newer = el.newer; 
      if (el.newer != null) el.newer.elder = el.elder; 

      if (oldest == el) oldest = el.newer; 
      if (oldest == null) oldest = el; 

      if (newest != null) newest.newer = el; 
      el.newer = null; 
      el.elder = newest; 
      newest = el; 
     } 
    } 
} 

在此函數的瓶頸是lock()操作者,這限制了對高速緩存訪​​問一次只有一個線程。

問題:是否有可能擺脫lock(syncQueue)這個函數,同時仍然保持隊列的完整性?

+0

上下文不清楚。這個類在多線程環境中如何使用?爲什麼你用於鎖定實例的變量不是靜態的? '最新'是靜態的嗎? 'TCacheable '看起來像什麼? – 2010-05-29 06:55:58

+0

對不起,更新了代碼。 Cache類實現了一個緩存算法,並且它的單個實例被構造來處理所有緩存的元素。 'newest',''''''變量以及'syncQueue'都與緩存實例相關,並且與存儲所有緩存元素的隊列相關。 – Andy 2010-05-29 06:59:56

+0

感謝您的編輯。儘管如此,仍然不清楚「最新」變量。它是靜態的嗎? – 2010-05-29 07:00:05

回答

0

最簡單的第一步是在if(newest!= el)塊內移動lock語句,因爲如果最新的== el,你不需要等待所有的鎖。

除此之外,你正在做一些條件分配。你真的有分析信息,導致你認爲這部分在性能方面存在問題嗎?

如果你真的確定優化這個課程是最好的利用你的時間,here's a PDF of the paper "Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms"Here's an excellent blog post that might be a little bit more straightforward

1

併發LRU緩存的訣竅不是去除鎖定 - 這是一個兔子洞 - 但分攤獲得它的需要。在讀取過程中,隊列最終可能與表格保持一致,但在寫入正確選擇受害者驅逐後應該保持一致。因此,您可以緩衝重新排序並避免鎖定爭用。我在我的Java實現中證明了這種方法的有效性:http://code.google.com/p/concurrentlinkedhashmap/

因此,雖然我可以提供解決方案來回答「是」您的問題,但更好的答案是您不需要移除鎖定,其實際需要。

+0

這是一個很好的答案。 – anthony 2010-05-29 07:24:06