синхронизирует с, случается до и семантика получения-выпуска - PullRequest
8 голосов
/ 14 декабря 2010

Мне нужна помощь в понимании синхронизации с отношением. Чем больше я читаю этот пример, пытаясь понять, тем больше я чувствую, что ничего не понимаю. Иногда я чувствую, что вот оно, у меня это есть, но после просмотра другого примера я снова запутываюсь. Пожалуйста, помогите мне сделать это правильно.

Говорят, что операция A синхронизируется с операцией B, если A является хранилищем некоторой атомарной переменной m с семантикой освобождения, B является загрузкой из той же переменной m с семантикой получения, а B считывает сохраненное значение А. Также сказано, что операция A происходит - перед операцией B, если

  • A выполняется в том же потоке, что и B, а A перед B в программном порядке или
  • A синхронизируется с B или
  • A происходит - до какой-либо другой операции C, а C - до B

OK. Если мы посмотрим на этот пример

thread0 выполняет | нить1 выполняет


магазин х (выпуск) | нагрузка х (приобретение)

сохраняет ли здесь x синхронизацию с загрузкой из x? Если здесь у нас есть отношение «синхронизируется с», то сохранение до x происходит до загрузки из x, поэтому все, что упорядочено перед сохранением до x в потоке 0, происходит до загрузки из x в потоке 1. Это означает, что здесь есть принудительное упорядочение. Это правильно? Но в этом случае я не понимаю, что означает часть определения "и B читает значение, сохраненное в A"? Если поток 1 быстрее, чем поток 0, он может прочитать старое значение. Итак, каковы здесь отношения и есть ли вообще отношения? Если нет, как я могу обеспечить эти отношения?

Заранее спасибо.

1 Ответ

5 голосов
/ 14 января 2011

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

Нет принудительного упорядочения между хранилищем и загрузкой в ​​примере.Любой из них может быть выполнен первым.A синхронизируется с B, когда операция сохранения выполняется перед загрузкой.Когда это происходит, все операции до сохранения (деблокирования) гарантированно выполняются до выполнения операций после загрузки (захвата).

Однако операция загрузки может выполняться до сохранения.В этом случае A не синхронизируется с B (поскольку условие «и B читает значение, сохраненное A» не соответствует действительности), и поэтому операции после загрузки могут выполняться перед операциями, предшествующими хранилищу.Порядок нечеткий.

Семантика выпуска гарантирует, что для определенного значения x мы будем знать, что операции, предшествующие хранилищу, будут выполнены до того, как мы сможем загрузить то же самое сохраненное значение во второй поток (и домы можем выполнить операции после загрузки).

Предположим, что счетчик и флаг инициализируются нулями, а оба потока выполняются параллельно:

thread0:
st          count, 1   (A)
st.release  flag, 1    (B)

thread1:
ld.acquire  flag       (C)
ld          count      (D)

Мы знаем, что происходит A- до того, как произойдет B и C - до D, потому что их порядок навязывается освобождением и приобретает семантику.Порядок B и C не определен.Он становится определенным только тогда, когда B синхронизируется с C, и тогда мы знаем, что A происходит до D (как A происходит до B, до C происходит до D).

В потоке 1 счет всегда равен 1если флаг равен 1. Если флаг равен 0, счетчик может быть 0 или 1. Мы могли бы проверить флаг, чтобы определить, установил ли другой поток значение для счетчика.

Без семантики получения и освобождения нагрузкии хранилища могут быть переупорядочены, и оба флага и счет могут быть либо 0, либо 1 без зависимости друг от друга.

Если мы хотим гарантировать, что B произойдет до C, мы можем использовать семафоры или некоторое другое ожиданиеи сигнальный механизм.В предыдущем примере мы могли принудительно установить порядок, ожидая установленного флага.

thread1:
ld.acquire  flag       (C)
repeat C while flag == 0
ld          count      (D)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...