ASP.NET Threading - двойная проверка блокировки - PullRequest
2 голосов
/ 26 января 2009

У меня есть метод расширения объекта HttpApplicationState для извлечения моего контейнера IoC из приложения. Этот же код также создаст контейнер, если он не существует.

У меня есть 2 вопроса:

  1. Является ли мой код действительно потокобезопасным, как я предполагаю, что он будет
  2. Считается ли это лучшей практикой работы с состоянием приложения

Код следующий:

private const string GlobalContainerKey = "UnityContainerKey";

public static IUnityContainer GetContainer(this HttpApplicationState application)
{
    var container = application[GlobalContainerKey] as IUnityContainer;

    if (container == null)
    {
        try
        {
            application.Lock();
            container = application[GlobalContainerKey] as IUnityContainer;

            if (container == null)
            {
                container = new UnityContainer();
                application[GlobalContainerKey] = container;
            }
        }
        finally
        {
            application.UnLock();
        }
    }

    return container;
}

Ответы [ 4 ]

3 голосов
/ 26 января 2009

нужно поставить

var container = application[GlobalContainerKey] as IUnityContainer;

также в блокировке, иначе многие потоки могут создать новый контейнер в последовательности.

private const string GlobalContainerKey = "UnityContainerKey";
private const object lockObject = new object();

public static IUnityContainer GetContainer(this HttpApplicationState application)
{
    var IUnityContainer container = null;

    lock (lockObject)
    {
        container = application[GlobalContainerKey] as IUnityContainer;
        if (container == null)
        {
            container = new UnityContainer();
            application[GlobalContainerKey] = container;
        }
    }

    return container;
}
1 голос
/ 26 января 2009

Двойная проверка с блокировкой используется внутри кода .NET Framework для одиночных кодов (см., Например, System.Web.Profile.ProfileManager).

Так что я думаю, что ваша реализация в порядке.

1 голос
/ 26 января 2009

Почему вы проверяете "container == null" в первый раз? Я думаю, что вы должны сначала заблокировать, а затем проверить, что контейнер нулевой. Между первым if и возвратом в других потоках могут происходить всякие хитрости

1 голос
/ 26 января 2009

Технически это не сработает, учитывая спецификацию EMCA. Джон Скит рассказывает об этом в своем C # FAQ:

http://www.yoda.arachsys.com/csharp/singleton.html

В частности, см. Раздел «Третья версия»

Я бы прочитал далее и использовал его предложение о том, как реализовать синглтон, чтобы увидеть, как реализовать то, что вы пытаетесь сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...