boost:: уникальный замок против boost:: Lock guard


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

означает ли это, что основная разница между unique_lock и lock_guard заключается в том, что с unique_lock мы должны явно вызвать

5 55

5 ответов:

во-первых, чтобы ответить на ваш вопрос. Нет, вам не нужно вызывать блокировку на unique_lock. Смотрите ниже:

unique_lock - это только класс блокировки с большим количеством функций. В большинстве случаев lock_guard будет делать то, что вы хотите, и будет достаточно.
В unique_lock имеет больше возможностей, чтобы предложить вам. Например, приуроченное ожидание, если вам нужен тайм-аут или если вы хотите отложить блокировку до более поздней точки, чем построение объекта. Так это сильно зависит от того, что вы хотите сделать. Кстати: следующие фрагменты кода делают то же самое.

boost::mutex mutex;
boost::lock_guard<boost::mutex> lock(mutex);

boost::mutex mutex;
boost::unique_lock<boost::mutex> lock(mutex);

первый может быть использован для синхронизации доступа к данным, но если вы хотите использовать переменные состояния нужно перейти на второй.

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

во-первых, оба lock_guard и unique_lock следует шаблону RAII, в простейшем случае использования замок приобретается во время строительства и автоматически разблокируется во время разрушения. Если это ваш вариант использования, то вам не нужна дополнительная гибкость unique_lock и lock_guard будет более эффективным.

в ключевое различие между обоими является unique_lock экземпляр не должен всегда владеть мьютексом, с которым он связан, находясь в lock_guard Он владеет мьютексом. Это значит unique_lock должен быть дополнительный флаг, указывающий, владеет ли он блокировкой, и еще один дополнительный метод " owns_lock ()", чтобы проверить это. Зная это, мы можем объяснить все дополнительные преимущества, которые эти флаги приносят с накладными расходами этих дополнительных данных, которые нужно установить и проверить

  1. замок не должен приниматься прямо на строительстве, вы можете передать флаг std::defer_lock во время его строительства, чтобы сохранить мьютекс разблокирован во время строительства.
  2. мы можем разблокировать его до завершения функции и не обязательно ждать, пока деструктор выпустит его, что может быть удобно.
  3. вы можете передать право собственности на замок из функции, это подвижные, а не копировать.
  4. он может использоваться с условными переменными, так как это требует блокировки мьютекса, условие проверено и разблокировано во время ожидания условия.

их реализация может быть найдена в разделе путь .../ повышение / поток / замки.ГЭС - и они сидят просто один рядом с другим:) короче говоря:

lock_guard это короткий простой служебный класс, который блокирует мьютекс в конструкторе и разблокирует в деструкторе, не заботясь о деталях.

unique_lock немного сложнее, добавляя довольно много функций, но он по-прежнему автоматически блокируется в конструкторе. Это называется unique_lock, потому что он вводит понятие" lock ownership " (см. Метод owns_lock ()).

если вы привыкли к pthreads(3):

  • boost::mutex = pthread_mutex_*
  • boost::unique_lock= pthread_rwlock_* используется для получения блокировки записи / исключения (т. е. pthread_rwlock_wrlock)
  • boost::shared_lock = pthread_rwlock_* используется для получения чтения / общих блокировок (т. е. pthread_rwlock_rdlock)

да boost::unique_lock и boost::mutex функция аналогично, но a boost::mutex обычно является более легким мьютексом веса для приобретения и выпуска. Что сказал shared_lock С уже приобретенным замком быстрее (и позволяет параллелизм), но это сравнительно дорого, чтобы получить unique_lock.

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


говоря о производительности: вот умеренно полезное сравнение задержек:

http://www.eecs.berkeley.edu/%7Ercs/research/interactive_latency.html

было бы неплохо, если бы я / кто-то мог сравнить относительная стоимость различных примитивов pthread_*, но в последний раз я смотрел,pthread_mutex_* было ~25us, тогда как pthread_rwlock_* было ~20-100us в зависимости от того, была ли уже приобретена блокировка чтения (~10us) или нет (~20us) или писатель (~100us). Вам нужно будет проверить, чтобы подтвердить текущие цифры, и я уверен, что это очень специфично для ОС.

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