c++ multithreading locking c++17

c++ - std:: lock_guard o std:: scoped_lock?



multithreading locking (3)

C ++ 17 introdujo una nueva clase de bloqueo llamada std::scoped_lock .

A juzgar por la documentación, se parece a la clase std::lock_guard ya existente.

¿Cuál es la diferencia y cuándo debo usarla?


Aquí hay una muestra y una cita de C ++ Concurrency in Action :

friend void swap(X& lhs, X& rhs) { if (&lhs == & rhs) return; std::lock(lhs.m, rhs.m); std::lock_guard<std::mutex> lock_a(lhs.m, std::adopt_lock); std::lock_guard<std::mutex> lock_b(rhs.m, std::adopt_lock); swap(lhs.some_detail, rhs.some_detail); }

vs.

friend void swap(X& lhs, X& rhs) { if (&lhs == &rhs) return; std::scoped_lock guard(lhs.m, rhs.m); swap(lhs.some_detail, rhs.some_detail); }

La existencia de std::scoped_lock significa que la mayoría de los casos en los que habría utilizado std::lock antes de c ++ 17 ahora se pueden escribir usando std::scoped_lock , con menos potencial de errores, lo que solo puede ser un buen ¡cosa!


La única e importante diferencia es que std::scoped_lock tiene un constructor variable que toma más de un mutex. Esto permite bloquear múltiples mutexes en un punto muerto evitando la forma como si se usara std::lock .

{ // safely locked as if using std::lock std::scoped_lock<std::mutex, std::mutex> lock(mutex1, mutex2); }

Anteriormente, tenía que bailar un poco para bloquear múltiples mutexes de manera segura usando std::lock como se explica en esta respuesta .

La adición del bloqueo de alcance hace que sea más fácil de usar y evita los errores relacionados. Puede considerar std::lock_guard desuso. El caso de argumento único de std::scoped_lock se puede implementar como una especialización y no tiene que temer sobre posibles problemas de rendimiento.

GCC 7 ya tiene soporte para std::scoped_lock que se puede ver here .

Para obtener más información, puede leer el documento estándar.


scoped_lock es una versión estrictamente superior de lock_guard que bloquea un número arbitrario de mutexes a la vez (usando el mismo algoritmo de evitación de bloqueo que std::lock ). En el nuevo código, solo debe usar scoped_lock .

La única razón por la que todavía existe lock_guard es por compatibilidad. No se puede eliminar simplemente porque se usa en el código actual. Además, resultó indeseable cambiar su definición (de unaria a variadic), porque también es un cambio observable y, por lo tanto, rompedor (pero por razones algo técnicas).