Последствия Lazy <T>и threadsafe false - PullRequest
4 голосов
/ 26 марта 2012

Каковы последствия использования класса Lazy<T> и маркировки isThreadSafe: false во время инициализации?

В случае, когда ленивому нужен доступ к элементам экземпляра, а не к статическим элементам, где ленивый инициализируется внутри конструктора класса, для этого автоматически требуется isThreadSafe: false во всех случаях?

Ответы [ 2 ]

5 голосов
/ 26 марта 2012

В случае, когда ленивому нужен доступ к элементам экземпляра, а не к статическим членам, где ленивый инициализируется внутри конструктора класса, автоматически ли для этого требуется isThreadSafe: false во всех случаях?

Нет- Аргумент isThreadSafe влияет только на то, как создается значение в Lazy<T>.

По сути, когда вы устанавливаете значение false, метод для создания значения просто создает значение, устанавливая его навнутреннее хранилище и верните значение.

Если вы установите его в значение true, то создание будет помещено в lock, предотвращая создание объекта более чем одним потоком.Это сопоставляется с LazyThreadSafetyMode.ExecutionAndPublication .

Вы также можете явно указать PublicationOnly, что позволит создать более одного значения, но затем использовать Interlocked.CompareExchange внутренне вместо блокировки, чтобы удостовериться, что значение первой завершенной подпрограммы создания является тем, которое используется для объекта.

Обратите внимание, что ни один из этих параметров вообще не влияет на то, какие члены используются для вычислениязначение - они влияют только на то, как создается само значение.Доступ ко всему кроме создания всегда потокобезопасен.Если вы инициализируете Lazy<T> экземпляр элемента в конструкторе класса, вы фактически гарантируете, что синхронизация не требуется, поэтому вы можете установить для isThreadSafe значение false - но это также будет означатьчто нет абсолютно никакой причины использовать Lazy<T> в этой ситуации, так как вы используете явную реализацию ...

2 голосов
/ 26 марта 2012

С MSDN :

Некоторые конструкторы Lazy<T> имеют параметр Boolean с именем isThreadSafe, который используется, чтобы указать, будет ли свойство Value использоваться из нескольких потоков. Если вы собираетесь получить доступ к свойству только из одного потока, передайте false, чтобы получить скромное преимущество в производительности. Если вы намереваетесь получить доступ к свойству из нескольких потоков, передайте true, чтобы указать экземпляру Lazy<T> правильную обработку условий гонки, при которых один поток генерирует исключение во время инициализации.

Вы написали ...

В сценарии, где lazy требуется доступ к элементам экземпляра, а не к статическим элементам, когда lazy инициализируется внутри конструктора класса, автоматически ли для этого требуется isThreadSafe: false во всех случаях?

Нет, это не имеет никакого отношения к экземпляру или статическому. Это связано с тем, будет ли лениво инициализированное значение получено в нескольких потоках или нет. Если к нему будут обращаться несколько потоков, используйте true, чтобы Lazy<T> обрабатывал условие гонки для вас. Если это не так, используйте false, чтобы Lazy<T> избегал взятия блокировки, которая даст вам очень небольшое, почти незаметное увеличение производительности (взятие неоспоримых блокировок ОЧЕНЬ быстро).

...