Я взял код DCL из книги Джо Даффи "Concurrent programming on windows"
class LazyInit<T> where T : class
{
private volatile T m_value;
private object m_sync = new object();
private Func<T> m_factory;
public LazyInit(Func<T> factory) { m_factory = factory; }
public T value
{
get
{
if (m_value == null)
{
lock (m_sync)
{
if (m_value == null)
{
m_value = m_factory();
}
}
}
return m_value;
}
}
}
там говорится, что пометка m_value volatile может предотвратить переупорядочивание записей, что приведет к тому, что другие потоки получат "non null объект с неинициализированными полями". Если проблема возникает только из-за возможной переупорядоченности записей, могу ли я просто использовать 'Volatile Write' вместо пометки файла volatile, как показано ниже? (Этот код выглядит немного неудобным для демонстрации, я просто хочу убедиться, можем ли мы использовать только volatile write вместо этого)
class LazyInit<T> where T : class
{
private object m_value;
private object m_sync = new object();
private Func<T> m_factory;
public LazyInit(Func<T> factory) { m_factory = factory; }
public T value
{
get
{
if (m_value == null)
{
lock (m_sync)
{
if (m_value == null)
{
Thread.VolatileWrite(ref m_value, m_factory());
}
}
}
return (T)m_value;
}
}
}
Смежный вопрос - версия Interlocked из книги
class LazylnitRelaxedRef<T> where T : class
{
private volatile T m_value;
private Func<T> m_factory;
public LazylnitRelaxedRef(Func<T> factory) { m_factory = factory; }
public T Value
{
get
{
if (m_value == null)
Interlocked.CompareExchange(ref m_value, m_factory(), null);
return m_value;
}
}
}
Поскольку ECMA-CLI специфицирует "Interlocked operation perform implicit acquire/release operations", нужен ли нам volatile в этом случае?