Я все это время делал замки неправильно? - PullRequest
4 голосов
/ 24 февраля 2012

Я читал эту статью о безопасности потоков в Singletons, и это заставило меня подумать, что я не понимаю метод lock.

Во второй версии авторимеет это:

public sealed class Singleton
{
    private static Singleton instance = null;
    private static readonly object padlock = new object();

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
}

В то время как я бы сделал что-то более похожее на это:

public sealed class Singleton
{
    private static Singleton instance = null;

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            lock (instance)
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
}

Почему бы вам использовать объект padlock вместо блокировки нужного объекта?заблокировать?

Ответы [ 3 ]

13 голосов
/ 24 февраля 2012

Что вы ожидаете случиться при первом обращении к свойству Instance до того, как получите объект для блокировки?

(Подсказка: lock(null) срывается ...)

Как отдельная мера, я почти всегда избегаю блокировки "фактического объекта" - потому что обычно может быть другой код, которому подвергается эта ссылка, и я не обязательно знаю, что будет блокироваться,Даже если ваша версия сработала , что произойдет, если какой-нибудь внешний код напишет:

// Make sure only one thread is ever in this code...
lock (Singleton.Instance)
{
    // Do stuff
}

Теперь никто другой не сможет даже получить экземпляр, пока этот кодвыполняется, потому что они будут заблокированы в получателе.Блокировка в геттере не предназначена для защиты от этого - она ​​предназначена только для защиты от множественного доступа внутри геттера .

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

I очень редко блокирует "нормальный" объект, если:

  • Iя не выставляю эту ссылку за пределы этого класса
  • Я уверен, что сам тип (который всегда будет иметь ссылку на this, конечно) не будет блокироваться сам по себе.

(Все это является причиной, по которой, конечно, тоже не стоит блокировать this ...)

По сути, я считаю, что идея разрешить вам блокировку любого объекта была плохой идеей.в Java, и это было плохим шагом, чтобы скопировать его в .NET: (

2 голосов
/ 24 февраля 2012

Блокировка на this или любом другом не приватном объекте опасна, поскольку может привести к взаимоблокировке, если кто-то еще попытается использовать этот объект для синхронизации.

Это не очень вероятно, поэтому люди могут иметь привычку делать это годами, даже не будучи укушенными. Но это все еще возможно, и стоимость частного экземпляра object, вероятно, недостаточно велика, чтобы оправдать риск.

1 голос
/ 24 февраля 2012

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

Конечно, возможноиметь это в качестве параметра блокировки.Но я думаю, что главная причина, по которой это не рекомендуется, заключается в том, что другой класс где-то может также использовать экземпляр вашего класса в качестве объекта блокировки, и это может вызвать проблемы с strage

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