Подтвердить что ты не робот

Когда использовать блокировку против MemoryBarrier в .NET

В .NET ключевое слово lock представляет собой синтаксический сахар вокруг Monitor.Enter и Monitor.Exit, поэтому вы можете сказать, что этот код

lock(locker)
{
  // Do something
}

совпадает с

Monitor.Enter(locker);
try
{
  // Do Something
}
finally
{
  Monitor.Exit(locker);
}

Однако платформа .NET также включает класс MemoryBarrier, который работает аналогичным образом

Thread.MemoryBarrier();
//Do something
Thread.MemoryBarrier();

Я запутался, как если бы я хотел использовать Thread.MemoryBarrier в версии lock/Monitor? Меня еще больше смущает Threading Tutorial, в котором говорится, что они функционируют одинаково.

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

Моя кишка говорит мне, что другое ключевое различие MemoryBarrier относится только к переменным, а не к методам.

Наконец, это не связано с существующим вопросом Когда использовать "volatile" или" Thread.MemoryBarrier() в потоковом коде блокировки? (С#), поскольку это фокусируется на ключевом слове volatile, который я понимаю его использование.

4b9b3361

Ответ 1

На мой взгляд, вы почти никогда не должны использовать Thread.MemoryBarrier. Это используется для незакрепленного кода - убедитесь, что изменения, сделанные в одном потоке, видны другому, не прибегая к стоимости блокировки. Он не контролирует синхронизацию потоков, в отличие от lock. Я не вижу, где в учебнике Джо он говорит, что MemoryBarrier "действует то же самое", что и lock. Не могли бы вы объяснить, откуда именно вы получаете это впечатление?

На мой взгляд, код блокировки на низком уровне слишком сложный для почти любого, кроме разработчиков, чье основное умение concurrency. Если я хочу написать какой-то незакрепленный код, я буду использовать более строгие строительные блоки, созданные этими разработчиками (например, Parallel Extensions в .NET 4.0), вместо того, чтобы пытаться свернуть свои собственные.

В качестве примера я недавно открыл глаза на точный смысл volatile, который не "всегда читается из основной памяти, всегда записывается непосредственно в основную память". (В моем собственном руководстве по потокам все еще есть это объяснение на данный момент - что-то мне нужно исправить в какой-то момент.) Это гораздо более тонкое, чем это. Это означает, что некоторые из моих предыдущих применений volatile могут быть неверными.