Использование барьеров памяти
-
20-09-2019 - |
Вопрос
В следующем примере кода, является ли барьер памяти в Фанка Требуется ли считывать самое современное значение?
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 будет читать самую последнюю ценность? (Я хочу убедиться, что недавнее значение фактически хранится в кэше процессора) [Wihout с использованием замков
Решение 5
Это на самом деле не имеет значения, так как на 32 -битных архитектурах можно прочитать разорванное в такой ситуации
Другие советы
Для меня выглядит как большая "нет". Thread.MemoryBarrier () только синхронизирует доступ к памяти в потоке, который его реализовал.
От MSDN:
Процессор, выполняющий текущий поток, не может переупорядочить инструкции таким образом, чтобы память обращалась к вызову в MemoryBarrier, выполняющую после доступа к памяти, которые следуют за вызовом в MemoryBarrier.
Я предлагаю вам сохранить DateTime как количество клещей (это типа «длинная», т.е. int64), вы можете легко преобразовать из клещей (New DateTime (Ticks)) и в Ticks (myDateTime.ticks). Затем вы можете использовать Interlocked.READ для чтения и взаимосвязанный.
Да, барьер памяти необходим, чтобы вы могли получить наиболее актуальное значение.
Если барьер памяти отсутствует, то поток X может прочитать значение M_BAR из собственной линии кэша, в то время как это значение не было записано обратно в основную память (изменение было локально для потока Y). Вы можете достичь того же эффекта, объявив переменную нестабильной:
Волатильный модификатор обычно используется для поля, доступ к которому доступ к нескольким потокам без использования оператора блокировки для сериализации доступа. Использование летучего модификатора гарантирует, что один поток извлекает наиболее современное значение, записанное другим потоком.
Хорошая запись по этому вопросу (вероятно, лучший) - это Джо Даффи: Нестабильное чтение и писание, и своевременность
Барьер памяти наступает то же самое, что и блокировка Wat, гарантируя, что поле получит свое последнее значение от памяти при входе в блокировку и будет записано в память перед выходом из блокировки.
Убедиться, что значение поля всегда читается или записывается в память и никогда не оптимизировалась, читая или написав его сначала в кэше ЦП, также может быть достигнуто с помощью летучих ключевых слов.
Если примитивные интегральные типы и эталонные типы DateTime не могут быть кэшированы в регистрах процессора AD, поэтому не нужно (и не может) быть объявлено с помощью нестабильного ключевого слова.