Дан фрагмент C++ с mutex: "std::lock(m1, m2); std::lock_guard g1(m1); std::lock_guard g2(m2);" — выявьте ошибку или неоптимальность и предложите корректную и безопасную альтернативу
Ошибка: вы сначала захватываете мьютексы через `std::lock(m1, m2)`, а затем создаёте `std::lock_guard` которые по умолчанию пытаются заново заблокировать мьютексы — это некорректно (повторная блокировка обычного `std::mutex` приведёт к ошибке/блокировке/исключению). Корректные и безопасные альтернативы: 1) Если хотите сохранить `std::lock` — используйте тег `std::adopt_lock`, чтобы `lock_guard` «принял» уже захваченные мьютексы: ``` std::lock(m1, m2); std::lock_guard g1(m1, std::adopt_lock); std::lock_guard g2(m2, std::adopt_lock); ``` 2) Проще и предпочтительнее (C++17): используйте `std::scoped_lock`, который атомарно захватывает все мьютексы и безопасно освобождает их при выходе из области видимости: ``` std::scoped_lock lock(m1, m2); ``` 3) Альтернатива с `std::unique_lock` (полезно, если нужен перенос/разблокировка вручную): ``` std::unique_lock lk1(m1, std::defer_lock); std::unique_lock lk2(m2, std::defer_lock); std::lock(lk1, lk2); // безопасно захватит оба ``` Резюме: либо используйте `std::adopt_lock` после `std::lock`, либо предпочтительнее — `std::scoped_lock`/`std::unique_lock` с `std::defer_lock` + `std::lock` для более простого и безопасного кода.
Корректные и безопасные альтернативы:
1) Если хотите сохранить `std::lock` — используйте тег `std::adopt_lock`, чтобы `lock_guard` «принял» уже захваченные мьютексы:
```
std::lock(m1, m2);
std::lock_guard g1(m1, std::adopt_lock);
std::lock_guard g2(m2, std::adopt_lock);
```
2) Проще и предпочтительнее (C++17): используйте `std::scoped_lock`, который атомарно захватывает все мьютексы и безопасно освобождает их при выходе из области видимости:
```
std::scoped_lock lock(m1, m2);
```
3) Альтернатива с `std::unique_lock` (полезно, если нужен перенос/разблокировка вручную):
```
std::unique_lock lk1(m1, std::defer_lock);
std::unique_lock lk2(m2, std::defer_lock);
std::lock(lk1, lk2); // безопасно захватит оба
```
Резюме: либо используйте `std::adopt_lock` после `std::lock`, либо предпочтительнее — `std::scoped_lock`/`std::unique_lock` с `std::defer_lock` + `std::lock` для более простого и безопасного кода.