Барьеры памяти и большие структуры? - PullRequest
2 голосов
/ 13 ноября 2009

Допустим, у меня есть структура, состоящая из 100 байтов. Какие гарантии я получил в отношении следующего кода?

m_myLargeStruct = someValue; // copying 100 bytes
Thread.MemoryBarrier();

// Executed by another thread, after "Thread.MemoryBarrier" was called by the first thread
Console.WriteLine(m_myLargeStruct.ToString());

Гарантирует ли модель памяти, что 100-байтовое копирование будет завершено после установки барьера памяти? или барьеры памяти применяются только для типов, которые соответствуют размеру архитектуры процессора? (4 байта для 32 бит и 8 байтов для 64 бит).
По этой ли причине ключевое слово volatile применяется только для примитивных типов? (если я объявляю 8-байтовый член как volatile, это означает, что для изменения его значения будет использоваться блокированный инстинкт? [поскольку атомарность не гарантируется для типов, больших 4 байтов на 32-битных машинах]).

Надеюсь, я был достаточно ясен ..:)
Спасибо

Ответы [ 5 ]

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

Если поток чтения не имеет барьера памяти, я не думаю , это вам очень поможет.

Лично я бы уклонился от:

  • Структуры, которые такие большие
  • Проникнуть в модель памяти, чтобы написать код без блокировки

... если у вас нет действительно важной причины для этого. невероятно трудно получить правильное кодирование без блокировки с изменяемыми данными; Я считаю, что даже эксперты борются. Я обычно нахожу, что подход «взять блокировку для каждого блока, обращающегося к данным» легче понять, и он хорош с точки зрения производительности в 99% случаев.

Я доверяю команде PFX в Microsoft в правильном кодировании без блокировок и в предоставлении им способов, с помощью которых я могу использовать их код для написания своих собственных программ без блокировок относительно легко. Я не доверяю себе, чтобы все было правильно. Если мне когда-либо понадобится явно использовать барьер памяти, это, вероятно, означает, что я слишком стараюсь.

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

Вам нужен еще один барьер памяти во втором потоке, перед WriteLine. (Если ваша система предоставляет асимметричные барьеры памяти, достаточно выполнить барьер Release после назначения и барьер Acquire перед WriteLine).

Размер данных не имеет значения.

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

Ясно, что ответ нет , или, скорее, у вас нет никаких гарантий ни о чем. Ничто не мешает операционной системе выгружать поток, записывающий в 100-байтовую структуру, до запуска потока, который печатает 100-байтовую структуру.

Барьер памяти используется, когда вы хотите координировать доступ к данным через флаг или другое атомарное значение. Я не знаю, что именно вы пытаетесь сделать, поэтому я не могу дать вам хороший пример кода о том, как вы должны это делать.

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

Вам необходим барьер памяти в обоих местах / потоках, и, конечно, вам нужна какая-то синхронизация между ними, чтобы барьер 2-го потока не запускался до первого потока.

В частности, потоку записи требуется барьер памяти «release», а потоку чтения - барьер памяти «acqu» (если базовая платформа поддерживает семантику отдельного барьера).

Если вы не просите из академического любопытства или не пишете свою собственную платформу, вам просто нужно использовать объект синхронизации из библиотеки / платформы / платформы. Попытка сделать все это правильно, сложно, и это уже сделано в предоставленных объектах синхронизации.

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

Ну, во-первых, у вас не должно быть такой большой структуры. Если вы не очень осторожны в использовании структуры, она будет медленнее, чем использование класса. Кроме того, он противоречит интуитивно понятной семантике значений структур.

Тем не менее, барьер памяти будет гарантировать, что структура будет скопирована. Оптимизация не будет перемещать какие-либо инструкции через барьер.

Ключевое слово volatile немного отличается. Это гарантирует, что никакие операции с переменной не оптимизируются, и это гарантирует порядок обращений к памяти. Однако для типов данных, к которым нельзя получить атомарный доступ, в большинстве случаев это бесполезно для многопоточности, поскольку вы все равно можете прочитать половину нового значения и половину старого значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...