c++ multithreading operating-system locking

mutex c++



Intenta atrapar con cerraduras en C++ (3)

¿Cuál es la garantía con C ++?

La garantía relevante en C ++ funciona de manera un poco diferente en comparación con la que usted menciona en Java. En lugar de un bloque finalmente , se basa en la destrucción de las variables automáticas que suceden en la salida del alcance, ya que el marco de la pila se desenrolla. Este desenrollado de pila se produce independientemente de cómo se salió del alcance, ya sea con gracia o debido a una excepción.

El enfoque preferido para el escenario con respecto a dichos bloqueos es usar RAII-style , como se implementó, por ejemplo, por std::lock_guard . mutex un objeto mutex que se pasa a su constructor, dentro del cual llama al método lock() mutex , después del cual el subproceso es propietario del mutex, y cuando se desenrolla la pila en la salida del visor, se llama a su destructor: dentro de lo que llama el método de unlock() mutex , liberándolo así.

El código se verá así:

std::mutex m; { std::lock_guard lock(m); // Everything here is mutex-protected. } // Here you are guaranteed the std::mutex is released.

En Java:

Lock lock = new ReentrantLock(); try{ lock.lock(); someFunctionLikelyToCauseAnException(); } catch(e){...} finally { lock.unlock(); }

Mi pregunta es con este ejemplo anterior, sabemos que el bloqueo siempre se desbloqueará porque, finalmente, siempre se ejecuta, pero ¿cuál es la garantía con C ++?

mutex m; m.lock(); someFunctionLikelyToCauseAnException(); /// ????

¿Cómo funcionará esto y por qué?


Para esto usamos la construcción de RAII-style std::lock_guard . Cuando usas

std::mutex m; { // start of some scope std::lock_guard lg(m); // stuff } // end of scope

lg asegurará que m se desbloqueará independientemente de la ruta que quede el alcance, ya que se destruye al salir del alcance y std::lock_guard s destructor llamará unlock

Incluso si se lanza una excepción, la pila se desenrollará (desenrollar la pila ) y ese proceso destruirá lg que a su vez llamará unlock garantizando que se libere el bloqueo.


Si se lanza una excepción durante la ejecución de un fragmento de código protegido por una sección crítica, es decir, los códigos entre "bloqueo ()" y "desbloqueo ()", significa que el objeto asociado con el que está funcionando el fragmento de código ya no es en un estado valido Esto puede o no puede revertirse mediante el desenrollado automático de la pila activada por la excepción, ya que puede haber ocurrido algún efecto secundario antes de que se lance la excepción (se envió un mensaje a través de un zócalo, se inició una máquina, por ejemplo) ). En este punto, el problema más importante aquí no es si se lanzará el mutex (la única garantía de usar lock_guard en su lugar). Es posible que haya algunos casos en que el mutex que aún está bloqueado sea el comportamiento deseable, y se pueda restablecer explícitamente después de que la persona que llama limpie todo el desastre.

Mi punto es: este no es un problema de idioma. Ninguna característica de idioma puede garantizar el correcto manejo de errores. No tome lock_guard y RAII como una bala de plata.