Использование барьеров памяти - PullRequest
1 голос
/ 13 ноября 2009

В следующем примере кода требуется ли барьер памяти в FuncA , чтобы обеспечить считывание наиболее актуального значения?

class Foo
{
   DateTime m_bar;

   void FuncA() // invoked by thread X
   {
      Thread.MemoryBarrier(); // is required?
      Console.WriteLine(m_bar);
   }

   void FuncB() // invoked by thread Y
   {
       m_bar = DateTime.Now;
   }       
}

РЕДАКТИРОВАТЬ : Если нет, как я могу гарантировать, что FuncA будет считывать самое последнее значение? (Я хочу убедиться, что последнее значение действительно хранится в кэше процессора) [без использования блокировок]

Ответы [ 5 ]

2 голосов
/ 13 ноября 2009

Я предлагаю вам хранить Datetime в виде числа тиков (оно имеет тип «long», то есть Int64), вы можете легко преобразовывать тики (новый DateTime (тики)) и тики (myDateTime.Ticks). Затем вы можете использовать Interlocked.Read для чтения значения и Interlocked.Exchange для записи значения в быстрых неблокирующих операциях.

2 голосов
/ 13 ноября 2009

Выглядит как большое "Нет" для меня. Thread.MemoryBarrier () синхронизирует доступ к памяти только в потоке, который его реализовал.

Из MSDN:

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

1 голос
/ 13 ноября 2009

Да, барьер памяти необходим, чтобы вы могли получить наиболее актуальное значение.

Если барьер памяти отсутствует, то поток X может прочитать значение m_bar из своей собственной строки кэша, пока это значение не было записано обратно в основную память (изменение было сделано локальным для потока Y ). Вы можете достичь того же эффекта, объявив переменную как volatile:

Модификатор volatile обычно используется для поля, к которому обращаются несколько потоков, без использования оператора блокировки для сериализации доступа. Использование модификатора volatile гарантирует, что один поток получит самое последнее значение, записанное другим потоком.

Хорошая статья по этому вопросу (вероятно, лучшая) Джо Даффи: Изменчивое чтение и запись и своевременность

0 голосов
/ 14 ноября 2009

Это на самом деле не имеет значения, так как на 32-битных архитектурах в такой ситуации можно получить разрывное чтение

0 голосов
/ 14 ноября 2009

Барьер памяти влияет на то же самое, что и блокировка wat, гарантируя, что поле получит последнее значение из памяти при входе в блокировку и запись в память перед выходом из блокировки.
Убедитесь, что значение поля всегда читается или записывается в память и никогда не оптимизируется при чтении или записи сначала это можно сделать в кеше процессора, используя ключевое слово volatile.
Если только примитивные целочисленные типы и ссылочные типы не могут быть кэшированы в регистрах ЦП, не нужно (и не может) быть объявлено с ключевым словом volatile.

...