Блокировка статического поля - PullRequest
2 голосов
/ 08 октября 2010

Я поддерживаю приложение, которое использует общую библиотеку, которая имеет статический экземпляр класса (ClassWrapper).Этот класс является в основном оболочкой для CacheManager шаблонов и практик Microsoft (v3.1 EL)

Библиотека размещается в веб-приложении, а также в приложении службы Windows (оба по своей сути являются многопоточными).) Существует множество мест в приложении, которое вызывает метод Add для этой оболочки, который, в свою очередь, вызывает Add для менеджера кэша, чтобы добавить элемент в менеджер кэша.

Как я понимаю, CacheManager не является поточно-ориентированным, и CacheWrapper не выполняет никакой блокировки для обеспечения безопасности потока при вызове Add.

Я не могу изменить код библиотеки напрямую, чтобы добавить синхронизациюи я собираюсь написать вспомогательный метод, подобный этому, и изменить все сайты вызовов для использования этого помощника вместо прямого вызова Add для оболочки.

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 - это статический экземпляр, отображаемый во всем пространстве процессов хоста (веб-приложение и служба Windows).

Любой совет или вотум доверия будут высоко оценены.

1 Ответ

2 голосов
/ 08 октября 2010

Я не уверен, что CacheManager не является поточно-ориентированным.Проверьте эту статью MSDN - в ней четко указано:

Каждый вызов метода, выполняемый через объект 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, вы бы взяли блокировку только на тот, который вы используете в настоящее время.

...