Какая операция 'volatile' необходима в Double checked locking в .NET

Я взял код 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 в этом случае?

8
задан Fei 26 November 2011 в 15:46
поделиться