Приветствую.
Хочу спроектировать тип аналогичный типу Lazy<T> или другими словами предоставляющий функционал аналогичный следующему сниппету:
private T? value = default;
public T Value
{
get
{
if (value.HasValue)
return value.Value;
return (value = ...).Value;
}
set
{
this.value = value;
}
}
Цели, которые я преследую:
1. Поведение данного типа при доступе к экземпляру из нескольких конкурентных потоков аналогично поведению типа Lazy<T> при использовании режима LazyThreadSafetyMode.ExecutionAndPublication за исключением того, что исключения полученные при использовании фабричного метода НЕ будут кэшированы. Таким образом только один конкурентный поток попытается создать экземпляр указанного типа; при успешном создании все ожидающие потоки получат одинаковое значение; если во время создания возникает необработанное исключение, оно будет повторно создано для каждого ожидающего потока, но оно не будет кэшироваться, и последующие попытки получить доступ к значению повторят попытку создания и могут быть успешными.
2. Тип является потокобезопасным
public class MyLazy<T>
{
private readonly Func<T> getAction = null;
private readonly object obj = new object();
private readonly bool canBeReseted = false;
private bool isExist = false;
private T value = default;
public bool HasValue => isExist;
public T Value
{
get
{
if (Volatile.Read(ref isExist))
return value;
lock (obj)
{
if (Volatile.Read(ref isExist))
return value;
value = getAction();
Volatile.Write(ref isExist, true);
}
return value;
}
set
{
lock (obj)
{
this.value = value;
Volatile.Write(ref isExist, true);
}
}
}
public MyLazy(Func<T> getAction, bool canBeReseted)
: this(getAction)
=> this.canBeReseted = canBeReseted;
public MyLazy(Func<T> getAction)
=> this.getAction = getAction;
public void Reset()
{
if (canBeReseted == false)
return;
lock (obj)
{
Volatile.Write(ref this.isExist, false);
}
}
}
Вопросы:
1. действительно ли данный тип является потокобезопасным?
2. может ли быть race condition который я пропустил?