Имеет ли pthread_mutex_lock семантику «происходит до»

Пройди через этот фрагмент

{
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
}

и предположим, что с точки зрения наблюдателя последовательность выполнения действительно

  1. резьба А — 1
  2. резьба А — 2
  3. резьба B — 3
  4. резьба B — 4

Может ли код на threadB "int tmp = global_a;" посмотри, какая нить установлена ​​на "global_a = 100;"?

Любое предложение приветствуется.

0

Решение

pthread_mutex_lock не мешает предыдущий инструкции должны быть заказаны после него.

Аналогичный, pthread_mutex_unlock не мешает с последующим инструкции должны быть заказаны до этого.

Но:

  1. В теме global_a = 100 случается, перед тем pthread_mutex_unlock(&b_mutex),

  2. В теме B pthread_mutex_lock(&b_mutex) случается, перед тем int tmp = global_a;,

И если вы наблюдаете

  1. 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

Другие решения

Если вы можете гарантировать последовательность выполнения — когда да. Если вы можете гарантировать последовательность выполнения, вам не нужно даже блокировать некоторые архитектуры.

Блокировка на самом деле делает три вещи:
1. Не допускайте одновременного выполнения другого кода. Увидеть. Здесь нет упоминания о памяти. Это просто гарантирует, что код в разных потоках не будет выполняться одновременно.
2. На некоторых архитектурах будут вставлены инструкции когерентности кэша. Что заставляет многопроцессорные системы сбрасывать данные в реальную память. Но вы не должны беспокоиться об этом случае, потому что прямо сейчас «многопроцессорный процессор является кеш-совместимым, если все записи в одну и ту же область памяти выполняются в некотором последовательном порядке» 3. В него вставлена ​​инструкция барьера памяти. Это для процессора, скажите это не связывайтесь с порядком выполнения.

Также ваш компилятор может тормозить вещи. Поэтому объявите вашу переменную как volatile.

1

По вопросам рекламы [email protected]