Mutex Lock: что означает «блокировка»? - PullRequest
17 голосов
/ 21 октября 2010

Я читал о многопоточности и доступе к общим ресурсам, и одна из многих (для меня) новых концепций - блокировка мьютекса.Похоже, я не могу понять, что на самом деле происходит с потоком, который обнаруживает, что «критическая секция» заблокирована.Во многих местах написано, что поток блокируется, но что это значит?Он приостановлен и возобновится ли после снятия блокировки?Или он попытается снова в следующей итерации цикла выполнения?

Причина, по которой я спрашиваю, заключается в том, что я хочу, чтобы системные события (мышь, клавиатура и т. Д.), Которые (очевидно) доставлялись в основной поток, обрабатывались в очень специфической части взапустить цикл моего вторичного потока.Итак, какое бы событие ни было доставлено, я ставлю в очередь в свою собственную структуру данных.Очевидно, что структура данных нуждается в блокировке мьютекса, потому что она модифицируется обоими потоками.Недостающий кусок головоломки: что происходит, когда событие доставляется в функцию в главном потоке, я хочу поставить его в очередь, но очередь заблокирована?Будет ли приостановлен основной поток или он просто перепрыгнет через заблокированный раздел и выйдет из области видимости (проиграв событие)?

Ответы [ 4 ]

14 голосов
/ 21 октября 2010

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

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

На самом деле очередь - это тот случай, когда вы можете избежать использования мьютекса. Например, Mac OS X (и, возможно, также iOS) предоставляет функции OSAtomicEnqueue() и OSAtomicDequeue() (см. man atomic или <libkern/OSAtomic.h>), которые используют атомарные операции для конкретного процессора, чтобы избежать использования блокировки.

Но почему бы просто не обработать события в главном потоке как часть основного цикла выполнения?

8 голосов
/ 21 октября 2010

Самый простой способ думать об этом состоит в том, что заблокированный поток переводится в состояние ожидания («ожидания»), пока мьютекс не будет освобожден потоком, удерживающим его. В этот момент операционная система «разбудит» один из потоков, ожидающих мьютекс, и позволит ему получить его и продолжить. Как будто операционная система просто кладет заблокированный поток на полку, пока у него не будет того, что нужно для продолжения. Пока ОС не заберет поток с полки, она ничего не делает. Точная реализация - какой поток пойдет дальше, будут ли они все разбужены или находятся в очереди - будет зависеть от вашей ОС и от того, какой язык / фреймворк вы используете.

3 голосов
/ 21 октября 2017

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

Слово «блокирование» является своего рода техническим омонимом.Люди могут использовать его для сна или просто ожидания .Этот термин следует понимать в контексте использования.

Блокировка означает ожидание - Предположим, что в системе SMP поток B хочет получить спин-блокировку, удерживаемую некоторым другим потоком A. Один изМеханизм состоит в том, чтобы отключить вытеснение и продолжать вращаться на процессоре, пока B не получит его.Другой механизм, вероятно, эффективный, состоит в том, чтобы позволить другим потокам использовать процессор, в случае, если B не получает его легкими попытками.Поэтому мы планируем поток B (поскольку приоритетное включение разрешено) и передаем процессор другому потоку C. В этом случае поток B просто ожидает в очереди планировщика и возвращается со своим ходом.Поймите, что B не спит, а просто пассивно ждет вместо занятого ожидания и горящих циклов процессора.В системах BSD и Solaris существуют структуры данных, такие как турникеты , для реализации этой ситуации.

Блокировка означает спящий режим - Если поток B вместо этого сделал системный вызов, например1017 * read () ожидание данных от сетевого сокета, оно не может продолжаться, пока не получит их.Поэтому некоторые тексты случайно используют термин «блокировка» как «... заблокирован для ввода-вывода» или «... при блокировании системного вызова».На самом деле, нить B довольно спит.Существуют специальные структуры данных, известные как очереди ожидания - очень похоже на роскошные залы ожидания в аэропортах :-).Поток будет разбужен, когда ОС обнаружит доступность данных, так же, как и оператор комнаты ожидания.

1 голос
/ 21 октября 2010

Блокировка означает только это.Это заблокировано.Это не будет продолжаться, пока не сможет.Вы не говорите, какой язык вы используете, но большинство языков / библиотек имеют объекты блокировки, где вы можете «попытаться» снять блокировку, а затем продолжить и сделать что-то другое в зависимости от того, преуспели ли вы или нет.

Но, например, в синхронизированных блоках Java ваш поток будет зависать до тех пор, пока не сможет получить монитор (мьютекс, блокировка).Интерфейс java.util.concurrent.locks.Lock описывает объекты блокировки, которые обладают большей гибкостью с точки зрения получения блокировки.

...