C ++ 11 equivalente a impulsar shared_mutex

¿Hay un C ++ 11 equivalente para el boost::shared_mutex . ¿O alguna otra solución para manejar una situación de lector múltiple / escritor individual en C ++ 11?

Intenté pero no conseguí shared_mutex en C ++ 11. Se ha propuesto para un estándar futuro. La propuesta está aquí .

Editar : Se aceptó una versión revisada (N3659) para C ++ 14.

Aquí hay una implementación:

http://howardhinnant.github.io/shared_mutex

http://howardhinnant.github.io/shared_mutex.cpp

Simple … No hay uno. No hay una implementación estándar de C ++ de un locking de lector-escritor .

Pero, tienes algunas opciones aquí.

  1. Te dejan en tus propios dispositivos para hacer tu propio locking de lector-escritor.
  2. Use una implementación específica de plataforma como Win32 , POSIX o Boost, como usted menciona.
  3. No use ninguno: use un mutex que ya existe en C ++ 11.

Seguir con el # 1 e implementar uno propio es una tarea aterradora y es posible acertar su código con condiciones de carrera si no lo hace bien. Existe una implementación de referencia que puede facilitar el trabajo.

Si desea un código independiente de la plataforma o no desea incluir bibliotecas adicionales en su código para algo tan simple como un locking lector-escritor, puede lanzar el n . ° 2 fuera de la ventana.

Y, el # 3 tiene un par de advertencias de las que la mayoría de la gente no se da cuenta: el uso de un locking de lector-escritor a menudo es menos eficaz y tiene un código más difícil de comprender que una implementación equivalente con un mutex simple. Esto se debe a la contabilidad adicional que tiene que pasar detrás de las escenas de la implementación de locking de lectores y guionistas.


Solo puedo presentarle sus opciones, realmente depende de usted sopesar los costos y beneficios de cada uno y escoger cuál funciona mejor.


Editar: C ++ 17 ahora tiene un tipo shared_mutex para situaciones donde los beneficios de tener varios lectores concurrentes superan el costo de rendimiento del shared_mutex .

No, no hay equivalente para boost::shared_mutex en C ++ 11.

Sin embargo, los lockings de lectura / escritura son compatibles en C ++ 14 o posterior:

  • C ++ 14 agregó std::shared_timed_mutex
  • C ++ 17 agregó std::shared_mutex

La diferencia es que std::shared_timed_mutex agrega operaciones de temporización adicionales. Implementa el concepto SharedTimedMutex , que es una extensión del concepto más simple de TimedMutex implementado por std::shared_mutex .


Tenga en cuenta que adquirir un locking para un mutex de lectura / escritura es más costoso que adquirir un std::mutex normal. Como consecuencia, un mutex de lectura / escritura no mejorará el rendimiento si tiene operaciones de lectura frecuentes, pero cortas. Es más adecuado para escenarios donde las operaciones de lectura son frecuentes y costosas. Para citar la publicación de Anthony Williams :

El costo de bloquear un shared_mutex es más alto que el de bloquear un plain std :: mutex, incluso para los hilos del lector. Esta es una parte necesaria de la funcionalidad — hay más estados posibles de un shared_mutex que un mutex, y el código debe manejarlos correctamente. Este costo viene tanto en el tamaño del objeto (que tanto en su implementación como en mi implementación POSIX incluye tanto un mutex simple como una variable de condición) y en el desempeño de las operaciones de locking y deslocking.

Además, shared_mutex es un punto de contención, y por lo tanto no escalable. Bloquear un shared_mutex necesariamente modifica el estado del mutex, incluso para un locking de lectura. En consecuencia, la línea de caché que contiene el estado shared_mutex se debe transferir a cualquier procesador que esté realizando una operación de locking o deslocking.

Si tiene muchos subprocesos realizando operaciones de lectura cortas y frecuentes, entonces en un sistema multiprocesador esto puede generar una gran cantidad de ping-pong de caché, lo que tendrá un impacto considerable en el rendimiento del sistema. En este caso, también puede adoptar el diseño más simple de simplemente usar un mutex simple, ya que los lectores están esencialmente serializados de todos modos.

Si las lecturas no son frecuentes, entonces no hay contención, por lo que no tiene que preocuparse por los lectores concurrentes, y un mutex simple será suficiente para ese escenario de todos modos.

Si las operaciones de lectura consumen mucho tiempo, entonces la consecuencia de esta contención es menos visible, ya que queda eclipsada por el tiempo empleado mientras se mantiene el locking de lectura. Sin embargo, realizar operaciones que requieren mucho tiempo mientras se mantiene un locking es un olor de diseño.

En la gran mayoría de los casos, creo que hay mejores alternativas a shared_mutex. Estos pueden ser un mutex simple, el soporte atómico de shared_ptr, el uso de un contenedor simultáneo cuidadosamente construido, o cualquier otra cosa, dependiendo del contexto.