Tengo una aplicación multiproceso que tiene que leer algunos datos con frecuencia 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 leer simultáneamente, y solo bloquearlos cuando se necesita una actualización (el subproceso de actualización podría esperar a que finalicen 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 ejemplo claro.
¿Alguien tiene un ejemplo simple que pueda usar para comenzar?
c++
multithreading
boost
mutex
boost-thread
kevin42
fuente
fuente
Respuestas:
Parece que harías algo como esto:
fuente
1800 INFORMACIÓN es más o menos correcta, pero hay algunos problemas que quería corregir.
También tenga en cuenta que, a diferencia de un shared_lock, solo un hilo puede adquirir un upgrade_lock a la vez, incluso cuando no está actualizado (lo que pensé que era incómodo cuando lo encontré). Entonces, si todos sus lectores son escritores condicionales, debe encontrar otra solución.
fuente
boost::unique_lock< boost::shared_mutex > lock(lock);
leerseboost::unique_lock< boost::shared_mutex > lock(
_access);
?Desde C ++ 17 (VS2015) puede utilizar el estándar para bloqueos de lectura y escritura:
Para la versión anterior, puede usar boost con la misma sintaxis:
fuente
typedef boost::unique_lock< Lock > WriteLock; typedef boost::shared_lock< Lock > ReadLock;
.Solo para agregar más 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 agregando la información importante de que solo un hilo puede tener un bloqueo de actualización incluso si no está actualizado, eso es importante ya que significa que no puede actualizar de un bloqueo compartido a un bloqueo único sin liberar primero el bloqueo compartido. (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 (no documentada) 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 único).
El hilo que está esperando un unique_lock en shared_mutex bloquea los nuevos lectores que ingresan, tienen que esperar la solicitud de los escritores. Esto asegura que los lectores no mueran de hambre a los escritores (sin embargo, creo que los escritores pueden matar de hambre a los lectores).
El hilo que está esperando a que se actualice un upgradeable_lock permite que otros hilos obtengan un bloqueo compartido, por lo que este hilo podría quedar muerto si los lectores son muy frecuentes.
Este es un tema importante a considerar y probablemente debería documentarse.
fuente
Terekhov algorithm
asegura que en1.
, el escritor no puede matar de hambre a los lectores. Mira esto . Pero2.
es cierto. Un upgrade_lock no garantiza la equidad. Mira esto .Utilice un semáforo con un recuento igual al número de lectores. Deje que cada lector cuente un 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 finalicen todas las lecturas y luego bloquee las lecturas mientras escribe.
fuente
Gran respuesta de Jim Morris, me topé con esto y me tomó un tiempo darme cuenta. Aquí hay un código simple que muestra que después de enviar una "solicitud" para un boost de unique_lock (versión 1.54) se bloquean todas las solicitudes de 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 no.
También (1) en la publicación de Jim Morris parece contradecir esto: Boost shared_lock. Leer preferido?
fuente