2010-10-08 86 views
2

我在維護一個應用程序,該應用程序使用一個公共庫,該庫具有一個類的靜態實例(ClassWrapper)。這個類是 微軟模式和實踐的的CacheManager(在EL V3.1)鎖定靜態字段

該庫在Web應用程序,並在Windows服務應用程序託管是以基本的包裝, (兩者本質上是多線程) 應用程序中有很多地方調用 這個包裝器上的Add方法,該包裝器又調用緩存管理器上的添加項將 項添加到緩存管理器。

據我所知,CacheManager不是線程安全的,並且CacheWrapper不會 執行任何鎖定以確保在添加調用中線程安全。

我不能直接修改庫代碼來添加同義詞代碼,並且考慮編寫像這樣的幫助器方法並修改所有的調用站點以使用此幫助器,而不是直接調用包裝器上的添加。

class CacheHelper 
{ 
    private static object _syncLock = new object(); 

    public static void Add<T>(CacheWrapper wrapper, string key, T value, int expireInMins) 
    { 
     lock (_syncLock) 
     { 
      wrapper.Add(key, value, expireInMins); 
     } 
    } 
} 

您是否發現此方法存在任何問題。我有點疲憊,因爲CacheWrapper是靜態的,因此固有的是_syncLock。 我感覺有點不安定鎖定靜態對象,但我沒有太多的選擇,因爲CacheWrapper是一個靜態實例,暴露在主機 (Web應用程序和Windows服務)的整個進程空間中。

任何建議或投票的信心將不勝感激。

+0

將'CacheWrapper'傳遞給'Add'方法有異味。鎖定的對象應與資源相關聯以防止併發訪問。你爲什麼不簡單地''鎖定'CacheWrapper'實例本身和/或隱藏'CacheHelper'類中的'CacheWrapper'實例以防止意外訪問而不鎖定? – dtb 2010-10-08 04:07:10

回答

2

我不確定CacheManager是不是線程安全的。檢查this MSDN article - 它明確規定:

通過 的CacheManager對象進行的每一個方法調用是線程安全的。

現在,即將實現,我不確定爲什麼要將CacheWrapper實例傳遞給您的方法。 CacheWrapper是靜態的情況下,你可以參考它直接如

class CacheHelper 
{ 

    private static CacheWrapper GetWrapper() 
    { 
     return [Lib Namespace].[Class Name].[Field Name referring to CacheWrapper]; 
    } 


    public static void Add<T>(string key, T value, int expireInMins) 
    { 
     var wrapper = GetWrapper(); 
     lock (wrapper) 
     { 
      wrapper.Add(key, value, expireInMins); 
     } 
    } 

    ... 

再次,GetWrapper是一個工廠方法和實施能夠改變 - 它可以使用一個靜態的代表獲得CacheWrapper實例或使用依賴注入來獲得參考CacheWrapper 。

這裏的另一個優點是,如果CacheWrapper有多個實例,那麼您只會鎖定當前使用的一個實例。