Boost:: unique_lock vs boost:: lock_guard
Я не очень понимаю разницу между этими двумя классами блокировки.
В форсированной документации говорится, что boost::unique_lock
не осуществляет блокировку автоматически.
Означает ли это, что основное различие между unique_lock
и lock_guard
заключается в том, что при unique_lock
мы должны явно вызывать функцию lock()
?
Ответы
Ответ 1
Сначала ответьте на свой вопрос. Нет, вам не нужно вызывать блокировку на unique_lock. См. Ниже:
Уникальный_lock - это только класс блокировки с большим количеством функций. В большинстве случаев lock_guard будет делать то, что вы хотите, и будет достаточно.
Уникальный_lock имеет больше возможностей, чтобы предложить вам. Например, время ожидания, если вам нужен тайм-аут, или если вы хотите отложить блокировку до более поздней точки, чем построение объекта. Так что это сильно зависит от того, что вы хотите сделать.
BTW: Следующие фрагменты кода делают то же самое.
boost::mutex mutex;
boost::lock_guard<boost::mutex> lock(mutex);
boost::mutex mutex;
boost::unique_lock<boost::mutex> lock(mutex);
Первый может использоваться для синхронизации доступа к данным, но если вы хотите использовать переменные условия, вам нужно перейти на второй.
Ответ 2
В настоящее время лучший проголосовавший ответ хорош, но он не уточнил мои сомнения, пока я не выкопал немного глубже, поэтому решил поделиться с людьми, которые могут находиться в одной лодке.
Во-первых, как lock_guard
, так и unique_lock
следует шаблону RAII, в простейшем случае блокировка приобретается во время построения и автоматически разблокируется во время уничтожения. Если это ваш прецедент, вам не нужна дополнительная гибкость unique_lock
и lock_guard
будет более эффективной.
Ключевое различие между ними заключается в том, что экземпляр unique_lock
не должен всегда содержать мьютекс, с которым он связан, а в lock_guard
ему принадлежит мьютекс. Это означает, что unique_lock
должен иметь дополнительный флаг, указывающий, владеет ли он блокировкой и другим дополнительным методом "owns_lock()", чтобы проверить это. Зная это, мы можем объяснить все дополнительные преимущества, которые эти флаги приносят с накладными расходами на дополнительные данные, которые необходимо установить и проверить
- Блокировка не должна иметь права при строительстве, вы можете передать флаг
std::defer_lock
во время его построения, чтобы сохранить мьютекс, разблокированный во время построения.
- Мы можем разблокировать его до завершения функции и не обязательно ждать, пока деструктор выпустит ее, что может быть удобно.
- Вы можете передать права собственности на блокировку с помощью функции, ее можно перемещать и не копировать.
- Он может использоваться с условными переменными, поскольку для этого требуется, чтобы мьютекс был заблокирован, условие проверено и разблокировано во время ожидания условия.
Ответ 3
Их реализация может быть найдена по пути... /boost/thread/locks.hpp - и они сидят один рядом с другим:) Чтобы суммировать вещи:
lock_guard - это простой простой класс утилиты, который блокирует мьютекс в конструкторе и разблокирует деструктор, не заботясь о деталях.
unique_lock немного сложнее, добавив много функций, но он по-прежнему автоматически блокируется в конструкторе. Он называется unique_lock, потому что он вводит концепцию "блокировка собственности" (см. Метод owns_lock()).
Ответ 4
Если вы привыкли к pthreads(3)
:
-
boost::mutex
= pthread_mutex_*
-
boost::unique_lock
= pthread_rwlock_*
используется для получения блокировок записи/исключения (т.е. pthread_rwlock_wrlock
)
-
boost::shared_lock
= pthread_rwlock_*
используется для получения блокировок чтения/совместного доступа (т.е. pthread_rwlock_rdlock
)
Да a boost::unique_lock
и a boost::mutex
функция аналогичным образом, но boost::mutex
, как правило, более легкий мутекс для получения и освобождения. Тем не менее, shared_lock
с уже приобретенным замком быстрее (и позволяет concurrency), но сравнительно дорого получить a unique_lock
.
Вы должны посмотреть под обложками, чтобы увидеть детали реализации, но это суть предполагаемых различий.
Говоря об эффективности: здесь умеренно полезное сравнение латентностей:
http://www.eecs.berkeley.edu/%7Ercs/research/interactive_latency.html
Было бы неплохо, если бы я/кто-то мог сравнить относительную стоимость разных примитивов pthread_ *, но в последний раз я выглядел, pthread_mutex_*
был ~ 25us, тогда как pthread_rwlock_*
был ~ 20-100us в зависимости от того, read lock уже был приобретен (~ 10us) или нет (~ 20us) или писатель (~ 100us). Вам нужно будет проверить текущие номера, и я уверен, что это очень специфичная ОС.
Ответ 5
Я думаю, что unique_lock может также использоваться, когда вам нужно подчеркнуть разницу между уникальными и совместными блокировками.