7

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

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

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

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

thread0 выполняет | thread1 выполняет


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

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

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

+0

отличная статья здесь http://preshing.com/20130823/the-synchronizes-with-relation/ – camino

ответ

4

Я не могу сказать, что я хорошо знаком с терминологией, но я так думаю. Я буду использовать определения .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) 

Мы знаем, что происходит, прежде, чем 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)