c++ - ¿Cuál es la diferencia entre "mutex" y "bloqueo"?
multithreading boost (3)
Estoy muy confundido acerca de la diferencia entre un bloqueo y mutex. En documentos de Boost, dice,
Tipos de bloqueo
- Plantilla de clase lock_guard
- Plantilla de clase unique_lock
- Plantilla de clase shared_lock
- Plantilla de clase upgrade_lock
- Plantilla de clase upgrade_to_unique_lock
- Clase específica de mutex scoped_try_lock
Tipos mutex
- Clase mutex
- Typedef try_mutex
- Clase timed_mutex
- Clase recursiva_mutex
- Typedef recursive_try_mutex
- Clase recursive_timed_mutex
- Clase shared_mutex
En otro artículo, veo funciones como esta,
boost::shared_mutex _access;
void reader()
{
boost::shared_lock< boost::shared_mutex > lock(_access);
// do work here, without anyone having exclusive access
}
void conditional_writer()
{
boost::upgrade_lock< boost::shared_mutex > lock(_access);
// do work here, without anyone having exclusive access
if (something) {
boost::upgrade_to_unique_lock< boost::shared_mutex > uniqueLock(lock);
// do work here, but now you have exclusive access
}
// do more work here, without anyone having exclusive access
}
Preguntas actualizadas
- ¿Alguien puede ofrecer alguna aclaración entre el "mutex" y el "bloqueo"?
- ¿Es necesario crear un shared_lock para un shared_mutex ? ¿Qué sucede si creo un unique_lock para un shared_mutex ?
- O si creo un shared_lock para un mutex , ¿significa que no se puede compartir el mutex entre varios subprocesos?
Los bloqueos pueden proporcionar la exclusión mutua pero no la sincronización de la condición. A diferencia de un semáforo, un bloqueo tiene un propietario, y la propiedad juega un papel importante en el comportamiento de un bloqueo.
ejemplo
class lockableObject { public void F() {
mutex.lock(); ...; mutex.unlock();
}
public void G() {
mutex.lock(); ...; F(); ...; mutex.unlock();
}
private mutexLock mutex; }
// method G() calls method F()
Lock mutex en la clase lockableObject se usa para convertir los métodos F () y G () en secciones críticas. Por lo tanto, solo un hilo a la vez puede ejecutarse dentro de un método de lockableObject. Cuando un hilo llama al método G (), el mutex está bloqueado. Cuando el método G () llama al método F (), mutex.lock () se ejecuta en F (), pero el subproceso que realiza la llamada no está bloqueado porque ya posee la exclusión mutua. Si mutex fuera un semáforo binario en lugar de un bloqueo, la llamada de G () a F () bloquearía el subproceso de llamada cuando mutex.P () se ejecutara en F (). (Recuerde que deben alternarse las operaciones de P () y V () en un semáforo binario). Esto crearía un punto muerto, ya que ningún otro subproceso podría ejecutarse dentro de F () o G ().
Estas son las diferencias entre los bloqueos y los semáforos binarios: 1 Para un semáforo binario, si se realizan dos llamadas a P () sin ninguna llamada intermedia a V (), la segunda llamada se bloqueará. Pero un hilo que posee un bloqueo y solicita la propiedad de nuevo no está bloqueado. (Tenga en cuenta que los bloqueos no siempre son recursivos, así que verifique la documentación antes de usar un bloqueo). 2 El propietario de las llamadas sucesivas a lock () y unlock () debe ser el mismo hilo. Pero las llamadas sucesivas a P () y V () pueden ser hechas por diferentes hilos.
Un mutex es un objeto de sincronización. Adquiere un bloqueo en un mutex al comienzo de una sección de código y lo libera al final, para garantizar que ningún otro hilo acceda a los mismos datos al mismo tiempo. Por lo general, un mutex tiene una duración igual a la de los datos que está protegiendo y varios subprocesos acceden a ese mutex.
Un objeto de bloqueo es un objeto que encapsula ese bloqueo. Cuando se construye el objeto, adquiere el bloqueo en el mutex. Cuando se destruye el bloqueo se libera. Normalmente crea un nuevo objeto de bloqueo para cada acceso a los datos compartidos.
Un mutex es un objeto que puede ser bloqueado. Un bloqueo es el objeto que mantiene el bloqueo. Para crear un bloqueo, necesitas pasarle un mutex.