Двоичный семафор как контроллер доступа к ресурсам: многопоточный POSIX

#multithreading #posix

#многопоточность #posix

Вопрос:

В соответствии с концепциями многопоточности, я узнал до сих пор:

МЬЮТЕКС: mutex_t объект может использоваться для управления доступом к ресурсу.

ДВОИЧНЫЙ СЕМАФОР: sem_t объект также может использоваться для управления доступом к ресурсу

Разница между двумя: концепция владения, т. Е. в случае mutex_t потока, который заблокировал mutex_t , только он может разблокировать его. Но в случае sem_t нет понятия владения, и, следовательно, любой поток может выполнять sem_post() над sem_t объектом. Это резонанс, в качестве которого он может использоваться Event signals .

Теперь предположим, что мой критический раздел выглядит как:

А) Использование mutex_t

 typedef struct {
int count;
pthread_mutex_t mutex;
}counter; 

counter count;
void increment(counter* c)
{
 pthread_mutex_lock(amp;(c->mutex));
 (c->count)  ;
 pthread_mutex_unlock(amp;(c->mutex));
}
  

Б) Использование sem_t
РЕДАКТИРОВАНИЯ: (двоичный семафор, т. е. инициализированный до 1)

 typedef struct {
int count;
sem_t sem;
}counter; 

counter count;
void increment(counter* c)
{
 sem_wait(amp;(c->sem));
 (c->count)  ;
 sem_post(amp;(c->sem));
}
  

В случае, когда B) до sem времени zero ни один поток не может войти в критическую секцию и, следовательно, обеспечить контроль доступа. Но предположим, что из-за какого-то события sem_post() выполняется какой-то другой поток, тогда он разрешит доступ к критической секции другим потокам.

В данном случае это на самом деле ошибка, а не надлежащее управление доступом.И, следовательно, программист должен быть осторожен с использованием binary semaphore для контроля доступа к ресурсам.

Я могу сделать вывод, что всегда лучше использовать mutex_t для контроля доступа и binary semaphore для event signalling .

Пожалуйста, дайте мне знать, правильно ли я понимаю или я что-то упускаю?

Комментарии:

1. К вашему сведению, этот вопрос может лучше подойти для другого сайта StackExchange, такого как CodeReview или суперпользователь.

2. На самом деле это не глючная ситуация, если вы не создадите ее глючной. Не публикуйте, когда вы не предполагаете публиковать. Тем не менее, мьютексы лучше подходят для этого, если они доступны для вас.

Ответ №1:

Мьютексы очень специфичны по своему назначению. Как вы сказали, они могут быть выпущены только потоком, в котором в данный момент находится мьютекс, и они допускают только один вход. По сути, мьютекс — это семафор, инициализированный числом 1, которое также проверяет, что поток, вызывающий post, является потоком, который последним вызвал wait (инвариантность «владения»).

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

Семафоры действительно имеют широкий спектр применений, поэтому я бы не назвал их «небезопасными». Например, предположим, что у вас есть некоторый ресурс, который позволяет запускать, скажем, всего 5 потребителей. Таким образом, вы бы защитили этот ресурс с помощью семафора, инициализированного на 5. Когда потребители вызывают ресурс, семафор будет отключаться, пока не достигнет нуля, после чего он заблокирует новых потребителей, пока работающие потребители не увеличат семафор. Это называется семафором подсчета.

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

Другим примером того, как можно было бы использовать семафор, была бы простая сигнальная ситуация, как вы упомянули:

Поток A помещает 10 заданий в пул потоков для их параллельного выполнения. С каждым заданием связан семафор, для которого изначально установлено значение 0. Когда задание выполнено пулом потоков, пул потоков отправляет сообщения в семафор заданий. Тем временем поток A ожидает семафора каждого задания, чтобы узнать, когда они завершатся.

Итак, мы видим множество применений семафора:

  • Создание мьютексов, где начальное значение = 1
  • Защита ограниченных ресурсов, где начальное количество = N, предел
  • Подсчет работы в очереди, где начальное значение равно = 0 и растет с ростом работы в очереди
  • Сигнализация завершения задания, где начальный счетчик = 0, а семафор используется для координации двух потоков.

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

Комментарии:

1. Я согласен со всем, что вы сказали, но если вы проверите заголовок моего вопроса — это использование двоичного семафора в качестве мьютекса для управления доступом к ресурсам. Я сопоставлял mutex_t и sem_t (только двоичный семафор) как контроллер доступа к ресурсам и является ли мой вывод правильным или нет?

2. Я ответил на ваш вопрос и не только, рассказав вам о свойствах мьютекса в терминах семафора. Мьютекс — это не что иное, как 1) семафор, инициализированный числом 1 и 2) блокирующий примитив, который требует, чтобы поток-владелец вызывал release (инвариантность владения). По крайней мере, не существует такого понятия, как «двоичный семафор», это не что иное, как семафор, который инициализируется числом 1. Я объяснил свойства каждого из них, теперь вам нужно использовать свои способности к логическому выводу, чтобы понять, что это значит.

3. И имейте в виду, что существует много применений для семафоров — они используются в широком диапазоне модальностей. Вам нужно понять всю картину. Да, при разработке программного обеспечения обычно существует сотня различных способов решения одной и той же проблемы. Я не могу перечислить их все для вас, поэтому вы должны думать сами.