lock_guard c++ multithreading boost mutex scoped-lock

c++ - lock_guard - Boost Mutex Scoped Lock



c++ lock_guard (2)

Estaba leyendo un tutorial de Boost Mutex en drdobbs.com y encontré este fragmento de código:

#include <boost/thread/thread.hpp> #include <boost/thread/mutex.hpp> #include <boost/bind.hpp> #include <iostream> boost::mutex io_mutex; void count(int id) { for (int i = 0; i < 10; ++i) { boost::mutex::scoped_lock lock(io_mutex); std::cout << id << ": " << i << std::endl; } } int main(int argc, char* argv[]) { boost::thread thrd1( boost::bind(&count, 1)); boost::thread thrd2( boost::bind(&count, 2)); thrd1.join(); thrd2.join(); return 0; }

Ahora entiendo que el objetivo de un Mutex es evitar que dos subprocesos accedan al mismo recurso al mismo tiempo, pero no veo la correlación entre io_mutex y std :: cout. ¿Este código simplemente bloquea todo dentro del alcance hasta que finalice el alcance?


Ahora entiendo que el objetivo de un Mutex es evitar que dos subprocesos accedan al mismo recurso al mismo tiempo, pero no veo la correlación entre io_mutex y std :: cout.

std::cout es un objeto global , por lo que puede verlo como un recurso compartido. Si accede a él simultáneamente desde varios subprocesos, esos accesos deben estar sincronizados de alguna manera, para evitar las carreras de datos y el comportamiento indefinido.

Quizás sea más fácil para usted darse cuenta de que el acceso simultáneo ocurre al considerar que:

std::cout << x

En realidad es equivalente a:

::operator << (std::cout, x)

Lo que significa que está llamando a una función que opera en el objeto std::cout , y lo hace desde diferentes subprocesos al mismo tiempo. std::cout debe ser protegido de alguna manera. Pero esa no es la única razón por la que el scoped_lock está ahí (sigue leyendo).

¿Este código simplemente bloquea todo dentro del alcance hasta que finalice el alcance?

Sí, bloquea io_mutex hasta que el objeto de bloqueo se salga del alcance (es un envoltorio RAII típico), lo que ocurre al final de cada iteración de su bucle for.

¿Por qué es necesario? Bueno, aunque en C ++ 11 se garantiza que las inserciones individuales en cout son seguras para subprocesos, las inserciones separadas pueden intercalarse cuando varios subprocesos emiten algo.

Tenga en cuenta que cada inserción a través del operator << es una llamada de función separada, como si estuviera haciendo:

std::cout << id; std::cout << ": "; std::cout << i; std::cout << endl;

El hecho de que el operator << devuelva el objeto de secuencia le permite encadenar las llamadas de función anteriores en una sola expresión (como lo ha hecho en su programa), pero el hecho de que tenga varias llamadas de función separadas sigue siendo válido.

Ahora mirando el fragmento de código anterior, es más evidente que el propósito de este bloqueo de ámbito es asegurarse de que cada mensaje del formulario:

<id> ": " <index> <endl>

Se imprime sin que sus partes se intercalan con partes de otros mensajes.

Además, en C ++ 03 (donde no se garantiza que las inserciones en cout sean seguras para subprocesos), el bloqueo protegerá el propio objeto cout que no se pueda acceder a él simultáneamente.


Un mutex no tiene nada que ver con nada más en el programa (excepto una variable condicional), al menos en un nivel superior. Un mutex tiene dos efectos: controla el flujo del programa e impide que varios subprocesos ejecuten el mismo bloque de código simultáneamente. También asegura la sincronización de la memoria. El problema importante aquí es que las exclusiones mutuas no están asociadas con los recursos y no impiden que dos subprocesos accedan al mismo recurso al mismo tiempo. Un mutex define una sección crítica de código, que solo puede ser ingresada por un hilo a la vez. Si todo el uso de un recurso en particular se realiza en secciones críticas controladas por el mismo mutex, entonces el recurso está efectivamente protegido por el mutex. Pero la relación es establecida por el codificador, asegurando que todo el uso tenga lugar en las secciones críticas.