2015-10-20 5 views
0

Я хочу, чтобы некоторые из моих объектов ленивых инициализируются как:C# с помощью отложенной инициализации и замок вместе

private static Lazy<MappingEngine> engine = new Lazy<MappingEngine>(() => 
{ 
    return new MappingEngine(); 
}) 

И я не хочу несколько потоков, чтобы получить доступ к этому объекту после его инициализации. Должен ли я использовать механизм блокировки для предотвращения этого или Lazy поддерживает безопасность потока таким образом? Использование Lazy и lock вместе не казалось правильным способом.

В docs говорится, что «Создание объекта поток Ленивого безопасен, не защищает лениво инициализирован объект. Если несколько потоков могут получить доступ к лениво инициализирован объекту, вы должны сделать его свойство и методы безопасны для многопоточного доступа.»

Является ли пользовательский тип, который является ленивым и который блокирует каждый раз engine.Value, называется логической задачей? Приведем пример:

public class MyLazyType<T> : Lazy<T> 
{ 
    private object lockObj = new object(); //not static since the reference to this class will be 

    public MyLazyType(Func<T> valueFactory) : base(valueFactory) 
    { 

    } 

    public new T Value 
    { 
     get 
     { 
      lock (lockObj) 
      { 
       return base.Value; 
      } 
     } 
    } 
} 

Использование:

private static MyLazyType<MappingEngine> engine = new MyLazyType<MappingEngine>(() => 
{ 
    return new MappingEngine(); 
}) 

ответ

2

Ваша специализация Lazy<T> не дает никаких дополнительных преимуществ. Решаемая выделены следующим образом:

var t1 = new Thread(()=>{ 
    myLazy.Value.SomeNonThreadsafeMethod(); 
}); 

var t2 = new Thread(()=>{ 
    myLazy.Value.SomeNonThreadsafeMethod(); 
}); 

t1.Start(); 
t2.Start(); 

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

+0

Если мы установим блокировку при доступе к myLazy.Value (как в MyLazyType <>), не делает ли это безопасным для всех вызовов SomeNonThreadsafeMethod? – sotn

+0

@sotn Нет, поскольку в момент, когда вызывается 'SomeNonThreadsafeMethod', мы больше не входим в область блокировки. – spender

+0

Упс :) Не знаю, что я думал, когда писал этот класс :) На самом деле, я подумал об этом, пока я отправляю вопрос. Благодарю. – sotn