2011-09-11 17 views
7

¿Podría alguien explicar el uso correcto de boost :: upgrade_lock. El código siguiente produce en un punto muertoActualización de boost :: shared_lock al bloqueo exclusivo

//Global 
typedef boost::shared_mutex Mutex; 
typedef boost::shared_lock<Mutex> ReadLock; 
typedef boost::upgrade_lock<Mutex> UpgradeLock; 
typedef boost::upgrade_to_unique_lock<Mutex> WriteLock; 
Mutex sharedMutex; 


//Multi threaded reader and writer 
{ 
    ReadLock read(sharedMutex); 

    for (int ii = 0; ii < vec.size(); ++ii) { 
     Element e = vec[ii]; 

     if (e.needsUpdating()) { 
      UpgradeLock upgrade(sharedMutex); 

      WriteLock write(upgrade) 

      //Do stuff 
     } 
    } 
} 

No punto muerto si puedo desbloquear el bloqueo de lectura con read.unlock() antes de actualizar. Pero parece que esto no debería ser necesario?

Respuesta

9

En la clase boost::shared_mutex (que implementa el concepto UpgradeLockable), un hilo único no debe intentar adquirir tanto un bloqueo compartido como uno actualizable (o único). En cualquier momento, UpgradeLockable puede tener N bloqueos compartidos retenidos (a través de lock_shared) y 1 bloqueo actualizable (a través del lock_upgrade). El bloqueo actualizable puede solicitar que se convierta en un bloqueo único, que bloquea hasta que pueda convertirse en titular exclusivo, lo que requiere que se liberen todos los bloqueos compartidos. Es imposible convertir un bloqueo compartido en un bloqueo único o un bloqueo compartido en un bloqueo actualizable sin liberar el bloqueo compartido primero.

Nota: el bloqueo actualizable no es exclusivo (se pueden retener otros bloqueos compartidos) solo porque tiene privilegios especiales para aumentar su fortaleza. Lamentablemente, no se permiten varios subprocesos actualizables al mismo tiempo.

En su caso, el mismo hilo está intentando usar lock_shared y lock_upgrade, lo que hará que se bloquee. Puede volver a escribirlo como se muestra a continuación, y no se estancará, pero sigue siendo un punto único de contención para todos los lectores, ya que solo 1 mantendrá el bloqueo de actualización a la vez. En ese caso, dependiendo de sus otras funciones, la complejidad de un shared_mutex podría no ser necesaria. Sin embargo, si otras funciones todavía están adquiriendo bloqueos compartidos, entonces lo siguiente funcionará como espera.

//Multi threaded reader and writer 
{ 
    // Only 1 thread can pass this. Other shared locks are also valid 
    UpgradeLock read(sharedMutex); 

    for (int ii = 0; ii < vec.size(); ++ii) { 
     Element e = vec[ii]; 

     if (e.needsUpdating()) { 
      // Blocks here until all shareds are released 
      WriteLock write(upgrade) 

      //Do stuff 
     } 
    } 
} 
+0

Desafortunadamente necesito varios lectores para poder ingresar al bucle al mismo tiempo, por lo que no puedo usar un bloqueo de actualización. Gracias por la explicación. –

Cuestiones relacionadas