Пройди через этот фрагмент
{
global_a = 100; // 1
{
pthread_mutex_lock(&b_mutex)
...
pthread_mutex_unlock(&b_mutex)
} // 2
}
поток B пройти через этот фрагмент
{
{
pthread_mutex_lock(&b_mutex)
...
pthread_mutex_unlock(&b_mutex)
} // 3
int tmp = global_a; // 4
}
и предположим, что с точки зрения наблюдателя последовательность выполнения действительно
Может ли код на threadB "int tmp = global_a;"
посмотри, какая нить установлена на "global_a = 100;"
?
Любое предложение приветствуется.
pthread_mutex_lock
не мешает предыдущий инструкции должны быть заказаны после него.
Аналогичный, pthread_mutex_unlock
не мешает с последующим инструкции должны быть заказаны до этого.
Но:
В теме global_a = 100
случается, перед тем pthread_mutex_unlock(&b_mutex)
,
В теме B pthread_mutex_lock(&b_mutex)
случается, перед тем int tmp = global_a;
,
И если вы наблюдаете
pthread_mutex_unlock(&b_mutex)
в теме случается, перед тем pthread_mutex_lock(&b_mutex)
в теме B.(другими словами, блокировка потока после ThreadA освобождает его), затем
global_a = 100;
в теме случается, перед тем int tmp = global_a;
в теме B. Итак, последний видит эффект первого.
Что говорит стандарт POSIX:
Что касается деталей синхронизации в стандарте POSIX, единственная ссылка, которую я нашел (и другие ссылаются на), это короткая глава о Синхронизация памяти. Это говорит о том, что pthread_mutex_lock
(и некоторые другие функции)
синхронизировать память по отношению к другим потокам
Кто-то интерпретирует это как полный барьер памяти гарантия, другие (и я) предпочитают думать о некоторых классический гарантии, когда блокировка и ожидание действий обеспечивает приобретение памяти семантические, разблокирующие и уведомляющие — освобождение памяти семантический. Смотрите, например, это почта.
Здесь нет случается, перед тем срок в POSIX. Но это может быть определено как обычно, принимая во внимание гарантии порядка памяти (в своей интерпретации).
Если вы можете гарантировать последовательность выполнения — когда да. Если вы можете гарантировать последовательность выполнения, вам не нужно даже блокировать некоторые архитектуры.
Блокировка на самом деле делает три вещи:
1. Не допускайте одновременного выполнения другого кода. Увидеть. Здесь нет упоминания о памяти. Это просто гарантирует, что код в разных потоках не будет выполняться одновременно.
2. На некоторых архитектурах будут вставлены инструкции когерентности кэша. Что заставляет многопроцессорные системы сбрасывать данные в реальную память. Но вы не должны беспокоиться об этом случае, потому что прямо сейчас «многопроцессорный процессор является кеш-совместимым, если все записи в одну и ту же область памяти выполняются в некотором последовательном порядке» 3. В него вставлена инструкция барьера памяти. Это для процессора, скажите это не связывайтесь с порядком выполнения.
Также ваш компилятор может тормозить вещи. Поэтому объявите вашу переменную как volatile.