Вопрос по – Mutex необходимы для защиты переменных условий

3

Как сказано, что Mutex необходимы для защиты переменных условий.

Ссылка здесь на фактическую переменную условия, объявленную какpthread_cond_t
ИЛИ ЖЕ
Нормальная переменная общего доступаcount чьи значения решают сигнализацию и ждут.
?

Ваш Ответ

4   ответа
0

что лучший вариант использования может помочь лучше объяснить условные переменные и их связанный мьютекс.

Я использую условные переменные posix для реализации того, что называетсяБарьерная синхронизация, По сути, я использую его в приложении, где у меня есть 15 потоков данных (плоскости данных), которые все делают одно и то же, и я хочу, чтобы они все подождали, пока все плоскости данных не завершат свою инициализацию. Как только все они закончили инициализацию (внутренней) плоскости данных, они могут начать обработку данных.

Вот код Обратите внимание, что я скопировал алгоритм из Boost, так как не мог использовать шаблоны в этом конкретном приложении:

void LinuxPlatformManager::barrierSync()
{
  // Algorithm taken from boost::barrier

  // In the class constructor, the variables are initialized as follows:
  //   barrierGeneration_ = 0;
  //   barrierCounter_ = numCores_; // numCores_ is 15
  //   barrierThreshold_ = numCores_;


  // Locking the mutex here synchronizes all condVar logic manipulation
  // from this point until the point where either pthread_cond_wait() or 
  // pthread_cond_broadcast() is called below
  pthread_mutex_lock(&barrierMutex_);

  int gen = barrierGeneration_;

  if(--barrierCounter_ == 0)
  {
    // The last thread to call barrierSync() enters here,
    // meaning they have all called barrierSync()
    barrierGeneration_++;
    barrierCounter_ = barrierThreshold_;

    // broadcast is the same as signal, but it signals ALL waiting threads
    pthread_cond_broadcast(&barrierCond_);
  }

  while(gen == barrierGeneration_)
  {
    // All but the last thread to call this method enter here
    // This call is blocking, not on the mutex, but on the condVar
    // this call actually releases the mutex
    pthread_cond_wait(&barrierCond_, &barrierMutex_);
  }

  pthread_mutex_unlock(&barrierMutex_);
}

Обратите внимание, что каждый поток, который входит вbarrierSync() метод блокирует мьютекс, который делает все между блокировкой мьютекса и вызовомpthread_cond_wait() или жеpthread_mutex_unlock() атомное. Также обратите внимание, что мьютексreleased/unlocked вpthread_cond_wait() как уже упоминалосьВот, В этой ссылке также упоминается, что поведениеundefined если ты позвонишьpthread_cond_wait() без предварительной блокировки мьютекса.

Еслиpthread_cond_wait() не снимать блокировку мьютекса, тогда все потоки будут блокироваться при вызовеpthread_mutex_lock() в началеbarrierSync() метод, и было бы невозможно уменьшитьbarrierCounter_ переменные (и не манипулировать связанными переменными) атомарно (ни в потоке безопасным способом), чтобы знать, сколько потоков вызвалиbarrierSync()

Итак, чтобы подвести итог всего этого, мьютекс, связанный с условной переменнойnot используется для защиты самой условной переменной, но вместо этого используется для создания логики, связанной с условием (barrierCounter_и т. д.) атомарный и потокобезопасный. Когда потоки блокируют ожидание выполнения условия, они фактически блокируют условную переменную,not на связанный мьютекс. И призыв кpthread_cond_broadcast/signal() разблокирует их

Вот еще один ресурс, связанный сpthread_cond_broadcast() а такжеpthread_cond_signal() для дополнительной ссылки.

Если вам нужно подождать только один раз, тоpthread_barrier_wait проще
6

read_cond_t or a normal shared variable count whose values decide the signaling and wait?

Ссылка на оба.

Мьютекс делает так, чтобы разделяемая переменная (count в вашем вопросе) может быть проверено, и если значение этой переменной не соответствует требуемому условию, ожидание, которое выполняется внутриpthread_cond_wait() будет происходить атомарно по отношению к этой проверке.

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

check the condition of count wait insode of pthread_cond_wait() if the condition isn't met yet.

pthread_cond_signal() не сохраняется и не сохраняется; - если наpthread_cond_t объект, сигнал ничего не делает. Таким образом, если бы не было взаимного исключения, делающего две операции, перечисленные выше, атомарными по отношению друг к другу, вы могли бы оказаться в следующей ситуации:

Thread A wants to do something once count is non-zero

Thread B will signal when it increments count (which will set count to something other than zero)

thread "A" checks count and finds that it's zero before "A" gets to call pthread_cond_wait(), thread "B" comes along and increments count to 1 and calls pthread_cond_signal(). That call actually does nothing of consequence since "A" isn't waiting on the pthread_cond_t object yet. "A" calls pthread_cond_wait(), but since condition variable signals aren't remembered, it will block at this point and wait for the signal that has already come and gone.

Мьютекс (если все потоки следуют правилам) делает так, чтобы элемент № 2 не мог находиться между пунктами 1 и 3. Единственный способ, которым поток & quot; B & quot; получит шанс на приростcount либо прежде чем А смотрит наcount или после "A" уже ждет сигнала.

@AnishaKaul, похоже, он говорит, что мьютекс используется для блокировки потоков в вызовеpthread_cond_wait(), но на самом деле потоки блокируют условную переменную при ожидании в этом вызове, а не мьютекс.
Таким образом, это означает, что, во-первых, «то же самое» Блокировка мьютекса будет использоваться поставщиком и поставщиком? И, следовательно, в то время как поставщик имеет дело с блокировкой, поставщик не может ничего сделать с кодом, который нуждается в той же самой блокировке? Имею ли я смысл? Aquarius_Girl
1

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

https://linux.die.net/man/3/pthread_cond_wait& # X200B;

Features of Mutexes and Condition Variables

It had been suggested that the mutex acquisition and release be decoupled from condition wait. This was rejected because it is the combined nature of the operation that, in fact, facilitates realtime implementations. Those implementations can atomically move a high-priority thread between the condition variable and the mutex in a manner that is transparent to the caller. This can prevent extra context switches and provide more deterministic acquisition of a mutex when the waiting thread is signaled. Thus, fairness and priority issues can be dealt with directly by the scheduling discipline. Furthermore, the current condition wait operation matches existing practice.

3

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

Больше информацииВот

Некоторый образец:

Поток 1 (ждет состояния)

pthread_mutex_lock(cond_mutex);
while(i<5)
{
 pthread_cond_wait(cond, cond_mutex);
}
pthread_mutex_unlock(cond_mutex);

Поток 2 (сигнализирует о состоянии)

pthread_mutex_lock(cond_mutex);
 i++;
if(i>=5)
{
  pthread_cond_signal(cond);
}
pthread_mutex_unlock(cond_mutex);

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

Теперь, в соответствии с вашим вопросом, если сигнальный поток сигнализирует первым, он должен был получить мьютекс, прежде чем сделать это, иначе первый поток мог бы просто проверить условие и увидеть, что оно не выполняется, и может перейти к условию ожидания, а так как второй поток уже сообщил об этом, никто не будет сигнализировать об этом после, и первый поток будет продолжать ждать вечно. Так что в этом смысле мьютекс предназначен как для условия & amp; условная переменная.

прочитайте ваш ответ Почему ты сказал:"since the second thread has already signalled it, no one will signal it there after"? Почему поток2 может снова подать сигнал без мьютекса? Aquarius_Girl
Почему thread2 должен сигнализировать это снова? Если взглянуть на это с точки зрения дизайна, как только условие будет выполнено, поток-2 будет сигнализировать об этом один раз, а теперь, если нам нужно спроектировать этот поток, он должен будет сигнализировать его снова, сколько раз поток-2 должен сигнализировать об этом снова? Когда он будет уверен, что поток-1 его получил? Именно такая проблема решает мьютекс.
Я хочу понять, как это имеет значение, если другой поток сообщает CV, прежде чем первый поток сможет его ждать. Видите, два потока делают разные работы. Первый поток все еще будет пытаться дождаться резюме, пока условие не станет истинным? Aquarius_Girl

Похожие вопросы