Почему pthread_mutex_lock используется, когда то же самое можно сделать программируемым способом? - PullRequest
1 голос
/ 17 августа 2011

Мы все знаем о семафоре и проблеме критической секции.

В pthreads это можно отсортировать с помощью pthread_mutex_lock( ) и pthread_mutex_unlock( ).

Но зачем нам эти системные вызовы, когда то же самое можно реализовать в коде, сделав что-то вроде:

flag = 0;
if (flag) // Thread1 enters and makes flag = 0
{
   flag = 0; // On entering critical section, flag is made 0 so that others can't enter
  // do some critical section operation
  flag = 1;
}
// Thread1 exits

Сделав то же самое, что и выше, решит ли это проблему критической секции?Если нет, то почему?

Ответы [ 4 ]

3 голосов
/ 19 августа 2011

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

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

  • методы синхронизации общеизвестно сложны и трудны для понимания.Поэтому лучше иметь проверенную библиотеку кода, которая выполняет эту функцию.Даже если бы можно было изобретать колесо еще миллион раз, иметь 99% этих реализаций с серьезными недостатками - не очень хорошая ситуация.Например, pthreads обрабатывает такие проблемы, как барьеры памяти и атомарность, которые не решаются должным образом в примере, который у вас есть в вашем вопросе.Рассматривая пример в вопросе: есть по крайней мере одна серьезная проблема;он имеет состояние гонки, при котором два потока могут одновременно войти в критическую секцию, поскольку проверка flag и установка его в 0 не выполняются атомарно.

2 голосов
/ 17 августа 2011

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

Кроме того, примите во внимание тот факт, что планировщик может вытеснить ваш поток в любом месте. Что произойдет, если поток A выполнит тест и будет прерван перед изменением flag, а потоку B будет разрешено выполнить тест и вскоре войти в критическую секцию, которая будет прервана. Там у вас будет две темы.

1 голос
/ 17 августа 2011

Поскольку вы пометили свой вопрос как «linux», можно добавить, что pthreads создаются поверх чего-то, называемого «futexes» или «быстрые мьютексы пространства пользователя». Как следует из названия, быстрый путь, а именно блокировка и разблокировка неконтролируемого мьютекса, НЕ требует системного вызова, все это делается в пользовательском пространстве. FWIW, AFAIK Windows также делает нечто подобное.

1 голос
/ 17 августа 2011

Во-первых, вы должны использовать атомарные операции с памятью (см. InterlockedCompareExchange () в MSVC и __sync_val_compare_and_swap () в GCC).

Во-вторых, этот код будет работать, но только если второй поток не должен ждать, когда первыйустанавливает флаг обратно в 1. Если это так, вы закончите циклом, который потребляет весь ваш процессор.В этом случае вы должны использовать что-то, что заставит ожидающий поток спать (например, pthread_mutex_lock ()).

...