Два объекта предназначены для разных целей. scoped_lock
- для простого случая, когда нужно заблокировать некоторое количество объектов мьютекса без тупиков. Блокировка одного мьютекса - это особый случай блокировки нескольких. Объект полностью неподвижен и очень прост.
unique_lock
предоставляет ряд функций, некоторые из которых особенно применимы при одновременной блокировке нескольких мьютексов.
Отсроченная блокировка. Откладывание должно быть все или ничего;вы либо откладываете блокировку всех мьютексов, либо ни одного из них. Непонятно, почему вы хотите отложить блокировку ряда мьютексов, поскольку вам придется отказаться от любых блокировок, которые были успешными, если какая-либо из них не удалась.
Блокировка по таймауту. Если вам нужно время ожидания 100 мс, значит ли это, что блокировка всех мьютексов должна занять не более 100 мс? То есть, если первые 3 блокируются немедленно, но следующий занимает 75 мс, следует ли считать тайм-аут, если пятый занимает 30 мс?
Принятие мьютексов. Весь смысл блокировки нескольких мьютексов за одну операцию состоит в том, чтобы избежать тупиков. Это делается путем блокировки взаимных исключений в порядке, который глобально согласован. То есть любое место, где вы блокируете эти объекты мьютекса с помощью std::lock
эквивалентных вызовов, будет блокировать их в том же порядке, независимо от того, что.
Если один из мьютексов уже заблокирован (и, следовательно, блокировка должнабыть принятым), то он был заблокирован за пределами std::lock
, и, таким образом, у вас нет гарантии, что он был заблокирован в глобально согласованном порядке. И это игнорирует сложность определения того, какие мьютексы следует использовать, а какие - блокировать.
Передача права собственности (будучи движимой). Это сомнительная перспектива для нескольких мьютексов по тем же причинам, что и принятие блокировок. Гарантии от взаимных блокировок работают только в том случае, если один вызов std::lock
или эквивалентный заблокирует все мьютексы, представляющие интерес. Если вы перемещаете владение этими scoped_lock
с, становится очень легко оказаться в той точке кода, где у вас есть несколько scoped_lock
с одной и той же областью действия, когда вы могли бы заблокировать все из них за один раз. Это вызывает тот самый тупик, который std::lock
был создан, чтобы избежать.
Обратите внимание, что std::lock
(основа функциональности scoped_lock
) даже не пытаетсяобеспечить любую из этих функций.
Может ли существовать специализация scoped_lock
, которая использует только один тип мьютекса, который предлагает поведение unique_lock
? Конечно. Но это нарушило бы цель scoped_lock
, которая должна была быть надежной блокировкой для блокировки взаимных мьютексов. Он lock_guard
устарел только случайно, поскольку у него был идентичный интерфейс в случае одного мьютекса.
Кроме того, наличие специализаций по шаблонам с совершенно разными интерфейсами и возможностями обычно не срабатывает. См. vector<bool>
в качестве примера.