Ejemplo de boost shared mutex (múltiples lecturas/una escritura)?


Tengo una aplicación multihilo que tiene que leer algunos datos a menudo, y ocasionalmente esos datos se actualizan. En este momento, un mutex mantiene el acceso a esos datos seguro, pero es caro porque me gustaría que varios subprocesos pudieran leerse simultáneamente, y solo bloquearlos cuando se necesita una actualización (el subproceso de actualización podría esperar a que terminen los otros subprocesos).

Creo que esto es lo que boost::shared_mutex se supone que debe hacer, pero no tengo claro cómo usarlo, y no he encontrado un claro ejemplo.

¿Alguien tiene un ejemplo simple que pueda usar para comenzar?

Author: newfurniturey, 2009-06-13

6 answers

Parece que harías algo como esto:

boost::shared_mutex _access;
void reader()
{
  // get shared access
  boost::shared_lock<boost::shared_mutex> lock(_access);

  // now we have shared access
}

void writer()
{
  // get upgradable access
  boost::upgrade_lock<boost::shared_mutex> lock(_access);

  // get exclusive access
  boost::upgrade_to_unique_lock<boost::shared_mutex> uniqueLock(lock);
  // now we have exclusive access
}
 95
Author: 1800 INFORMATION,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-07 22:47:39

LA INFORMACIÓN de 1800 es más o menos correcta, pero hay algunas cuestiones que quería corregir.

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
}

void unconditional_writer()
{
  boost::unique_lock< boost::shared_mutex > lock(_access);
  // do work here, with exclusive access
}

También tenga en cuenta, a diferencia de un shared_lock, solo un solo hilo puede adquirir un upgrade_lock a la vez, incluso cuando no se actualiza (que pensé que era incómodo cuando me encontré con él). Entonces, si todos tus lectores son escritores condicionales, necesitas encontrar otra solución.

 153
Author: mmocny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-19 09:12:49

Puede usar boost para crear un bloqueo de lectura-escritura:

#include <boost/thread/locks.hpp>
#include <boost/thread/shared_mutex.hpp>

typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock > WriteLock;
typedef boost::shared_lock< Lock > ReadLock;

Lock myLock;


void ReadFunction()
{
    ReadLock r_lock(myLock);
    //Do reader stuff
}

void WriteFunction()
{
     WriteLock w_lock(myLock);
     //Do writer stuff
}
 42
Author: Yochai Timmer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-03 16:05:31

Solo para agregar algo más de información empírica, he estado investigando todo el problema de los bloqueos actualizables, y Ejemplo para boost shared_mutex (múltiples lecturas/una escritura)? es una buena respuesta agregar la información importante de que solo un hilo puede tener un upgrade_lock incluso si no se actualiza, eso es importante ya que significa que no puede actualizar de un bloqueo compartido a un bloqueo único sin liberar el bloqueo compartido primero. (Esto se ha discutido en otra parte, pero el hilo más interesante está aquí http://thread.gmane.org/gmane.comp.lib.boost.devel/214394 )

Sin embargo, encontré una diferencia importante (indocumentada) entre un hilo esperando una actualización a un bloqueo (es decir, necesita esperar a que todos los lectores liberen el bloqueo compartido) y un bloqueo de escritor esperando lo mismo (es decir, un bloqueo unique_lock).

  1. El hilo que está esperando un unique_lock en el shared_mutex bloquea cualquier nuevo lector que entra, tienen que esperar la solicitud de los escritores. Esto asegura los lectores no matan de hambre a los escritores (sin embargo, creo que los escritores podrían matar de hambre a los lectores).

  2. El hilo que está esperando un upgradeable_lock para actualizar permite a otros hilos obtener un bloqueo compartido, por lo que este hilo podría morir de hambre si los lectores son muy frecuentes.

Este es un tema importante a considerar, y probablemente debería documentarse.

 16
Author: Jim Morris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:23

Utilice un semáforo con un recuento igual al número de lectores. Deje que cada lector tome un conteo del semáforo para leer, de esa manera todos pueden leer al mismo tiempo. Luego deje que el escritor tome TODOS los recuentos de semáforos antes de escribir. Esto hace que el escritor espere a que terminen todas las lecturas y luego bloquee las lecturas mientras escribe.

 2
Author: R Virzi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-11-20 07:31:44

Gran respuesta por Jim Morris, me tropecé con esto y me llevó un tiempo darme cuenta. Aquí hay un código simple que muestra que después de enviar una "solicitud" para un boost unique_lock (versión 1.54) bloquea todas las solicitudes shared_lock. Esto es muy interesante ya que me parece que elegir entre unique_lock y upgradeable_lock permite si queremos prioridad de escritura o ninguna prioridad.

También (1) en el post de Jim Morris parece contradecir esto: Aumenta shared_lock. Leer preferido?

#include <iostream>
#include <boost/thread.hpp>

using namespace std;

typedef boost::shared_mutex Lock;
typedef boost::unique_lock< Lock > UniqueLock;
typedef boost::shared_lock< Lock > SharedLock;

Lock tempLock;

void main2() {
    cout << "10" << endl;
    UniqueLock lock2(tempLock); // (2) queue for a unique lock
    cout << "11" << endl;
    boost::this_thread::sleep(boost::posix_time::seconds(1));
    lock2.unlock();
}

void main() {
    cout << "1" << endl;
    SharedLock lock1(tempLock); // (1) aquire a shared lock
    cout << "2" << endl;
    boost::thread tempThread(main2);
    cout << "3" << endl;
    boost::this_thread::sleep(boost::posix_time::seconds(3));
    cout << "4" << endl;
    SharedLock lock3(tempLock); // (3) try getting antoher shared lock, deadlock here
    cout << "5" << endl;
    lock1.unlock();
    lock3.unlock();
}
 2
Author: dale1209,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:14