Как сделать синтаксис блокировки с двойной проверкой менее подробным? - PullRequest
2 голосов
/ 30 июля 2009

В C # у меня есть следующий чрезвычайно подробный синтаксис для извлечения простого списка элементов из базы данных:

if (malls == null)
{
    lock (_lock)
    {
        if (malls == null)
        {
            using (var session = NhibernateHelper.OpenSession())
            {
                malls = session.CreateCriteria<Mall>()
                    .AddOrder(Order.Asc("Name")).List<Mall>();

                CacheManager.Set(CACHE_KEY, malls, TimeSpan.FromMinutes(CACHE_DURATION));
            }
        }
    }
}

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

Ответы [ 2 ]

8 голосов
/ 30 июля 2009

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

Двойная проверка блокировки - это механизм для достижения этого, но, как вы правильно заметили, многословие механизма полностью перебивает смысл кода.

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

Однако есть лучший способ. Лучше не делать это самостоятельно, а позволить специалисту мирового уровня по многопоточности сделать это за вас. Таким образом, вам не нужно беспокоиться о том, чтобы сделать это правильно. Джо Даффи должен беспокоиться о том, чтобы сделать это правильно. Как мудро говорит Джо, вместо того, чтобы повторять механизм блокировки повсюду, напишите его один раз и затем используйте абстракцию.

Код Джо здесь:

http://www.bluebytesoftware.com/blog/PermaLink,guid,a2787ef6-ade6-4818-846a-2b2fd8bb752b.aspx

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

1 голос
/ 30 июля 2009

Чтобы уменьшить шум, вы можете сделать это:

public List<Mall> Malls()
{
    EnsureMallsInitialized();
    return malls;
}

private void EnsureMallsInitialized()
{
    if (malls == null) // not set
    lock (_lock)       // get lock
    if (malls == null) // still not set
    {
        InitializeMalls();
    }        
}

private void InitializeMalls()
{
    using (var session = NhibernateHelper.OpenSession())
    {
        malls = session.CreateCriteria<Mall>()
            .AddOrder(Order.Asc("Name")).List<Mall>();

        CacheManager.Set(CACHE_KEY, malls, TimeSpan.FromMinutes(CACHE_DURATION));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...