Турникет против Mutex - PullRequest
       42

Турникет против Mutex

0 голосов
/ 01 декабря 2018

Вопрос связан с механизмом синхронизации под названием Турникет.Примеры реализаций и документации можно найти здесь , здесь и здесь .После некоторых исследований я все еще не могу найти ответы на следующие вопросы:

  • Какую проблему решает турникет?
  • Какое преимущество может предложить турникет по сравнению с мьютексом?
  • Каково отношение собственности между ниткой и турникетом?(если есть).
  • Если мы снизим сложность этих реализаций, какова минимальная структура турникета?

1 Ответ

0 голосов
/ 28 декабря 2018

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

Какую проблему решает турникет?Какое преимущество может предложить турникет по сравнению с мьютексом?Каково отношение собственности между потоком и турникетом?(если есть).

Турникет может помочь уменьшить количество мьютексов (или любого другого блока синхронизации).Когда мы хотим защитить объект с помощью некоторого замка с помощью турникетов, замок становится легким объектом, который делегирует все операции турникету.Каждая нить может быть связана не более чем с одним турникетом.Отсюда #turnstiles ≤ #threads.Такой подход помогает уменьшить количество неактивных блокировок.Однако нет никакого явного владения между потоками и турникетами AFAIK.

Если мы уменьшим сложность этих реализаций, какова минимальная структура турникета с минимальными затратами?

Мы можем реализовать наивный турникет следующим образом.

Выделите глобальный пул Turnstiles с операциями get и put (очевидно, он должен быть потокобезопасным).Стек без блокировки может быть относительно простой и эффективной реализацией для пула.TurnstileLock - это объект, который заменит наши блокировки и мьютексы и передаст ответственность Turnstile.TurnstileLock содержит обнуляемый указатель на Turnstile.

Когда какой-то поток хочет войти в критическую секцию, охраняемую TurnstileLock, он проверяет, является ли TurnstileLock.currentTurnstile нулевым (по умолчанию он должен быть нулевым).

  • Если ноль равен, поток берет турникет из пула и присваивает ему TurnstileLock.currentTurnstile, увеличивает TurnstileLock.currentTurnstile.waitingCount и входит в критическую секцию.
  • В противном случае поток долженувеличивайте TurnstileLock.currentTurnstile.waitingCount и ждите некоторую переменную условия, которая должна быть доступна через currentTurnstile

Когда какой-либо поток хочет покинуть критическую секцию (или снять блокировку), он должен проверить, TurnstileLock.currentTurnstile.waitingCount > 0 (после уменьшения)

  • Если да, то необходимо уведомить переменную условия, в которой спят другие потоки.
  • Иначе положить TurnstileLock.currentTurnstile обратно в пул и установить TurnstileLock.currentTurnstile до нуля
...