Подтвердить что ты не робот

Boost:: unique_lock vs boost:: lock_guard

Я не очень понимаю разницу между этими двумя классами блокировки. В форсированной документации говорится, что boost::unique_lock не осуществляет блокировку автоматически.

Означает ли это, что основное различие между unique_lock и lock_guard заключается в том, что при unique_lock мы должны явно вызывать функцию lock()?

4b9b3361

Ответ 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 может также использоваться, когда вам нужно подчеркнуть разницу между уникальными и совместными блокировками.