Tengo varios hilos que llaman simultáneamente push_back()
en un objeto compartido de std::vector
. ¿Es seguro el hilo std::vector
? ¿O necesito implementar el mecanismo yo mismo para que sea seguro?
Quiero evitar hacer extra "bloqueo y liberación" trabajo porque soy un usuario de biblioteca en lugar de un diseñador de biblioteca. Espero buscar soluciones existentes de subprocesos seguros para vector. ¿Qué hay de boost::vector
, que fue introducido recientemente de impulso 1.48.0 en adelante. ¿Es seguro para subprocesos?¿Es seguro el hilo std :: vector o boost :: vector?
Respuesta
El estándar C++ ofrece ciertas garantías de enhebrado para todas las clases en la biblioteca estándar de C++. Estas garantías pueden no ser lo que esperaría que fueran, pero para todas las clases de bibliotecas C++ estándar se hacen ciertas garantías de seguridad de subprocesos. Sin embargo, asegúrese de leer las garantías, ya que las garantías de subprocesamiento de los contenedores estándar de C++ generalmente no se alinean con lo que usted desearía. Para algunas clases se hacen garantías diferentes, generalmente más fuertes, y la respuesta a continuación se aplica específicamente a los contenedores. Los contenedores tienen esencialmente las siguientes garantías de hilo de seguridad:
- puede haber múltiples lectores concurrentes del mismo contenedor
- si hay un escritor, no habrá más escritores y no hay lectores
Normalmente no son lo que las personas querrían como garantías de seguridad de subprocesos, pero son muy razonables dada la interfaz de los contenedores estándar: están destinados a ser utilizados de manera eficiente en ausencia de múltiples hilos de acceso. Agregar cualquier tipo de bloqueo para sus métodos interferiría con esto. Más allá de esto, la interfaz de los contenedores no es realmente útil para ninguna forma de bloqueo interno: generalmente se usan múltiples métodos y los accesos dependen del resultado de accesos previos. Por ejemplo, después de haber comprobado que un contenedor no es empty()
, se puede acceder a un elemento. Sin embargo, con el bloqueo interno no hay garantía de que el objeto aún esté en el contenedor cuando realmente se acceda a él.
Para cumplir con los requisitos que brindan las garantías anteriores, probablemente deba utilizar alguna forma de bloqueo externo para los contenedores accedidos simultáneamente. No sé sobre los contenedores de impulso, pero si tienen una interfaz similar a la de los contenedores estándar, sospecho que tienen exactamente las mismas garantías.
Las garantías y requisitos se dan en 17.6.4.10 [res.on.objects] párrafo 1:
El comportamiento de un programa es indefinido si las llamadas a funciones de biblioteca estándar a partir de diferentes hilos pueden introducir un datos carrera. Las condiciones bajo las cuales esto puede ocurrir se especifican en 17.6.5.9. [Nota: la modificación de un objeto de un tipo de biblioteca estándar que se comparte entre hilos corre el riesgo de un comportamiento indefinido a menos que los objetos de ese tipo se especifiquen explícitamente como compartibles sin razas de datos o el usuario proporcione un mecanismo de bloqueo. -endnote]
... y 17.6.5.9 [res.on.data.races]. Esta sección esencialmente detalla la descripción más informal en el no.
Eso se denomina reentrancy :) – vines
Sería [reentrancy] (http://en.wikipedia.org/wiki/Reentrancy_%28computing%29) si fuera solo función. Sin embargo, hay objetos involucrados que están garantizados para no ser modificados por las operaciones de lectura. Además, reentrada se refiere a la característica de ser recurrentemente invocable en programas de un solo hilo. –
Por "lector" y "escritor", usted está hablando de la estructura del contenedor, y no escribe en los objetos adentro, ¿correcto? Por ejemplo, escribir en 3 elementos vectoriales diferentes, y leer desde un cuarto de otros diez hilos, se permitiría todo al mismo tiempo, siempre y cuando ninguno esté insertando o eliminando elementos. Las reglas de validez del iterador parecen relevantes aquí. –
Tengo varios subprocesos simultáneamente llamando a push_back() en un objeto compartido de std :: vector. ¿Es seguro el hilo std :: vector?
Esto es inseguro.
¿O necesito implementar el mecanismo yo mismo para hacerlo seguro?
Sí.
Quiero evitar el trabajo adicional de "bloqueo y liberación" porque soy un usuario de la biblioteca en lugar de un diseñador de la biblioteca. Espero buscar soluciones existentes de subprocesos seguros para vector.
Bueno, la interfaz del vector no es óptima para el uso concurrente. Está bien si el cliente tiene acceso a un bloqueo, pero para la interfaz para el bloqueo abstracto para cada operación - no. De hecho, la interfaz de vector no puede garantizar la seguridad del hilo sin un bloqueo externo (suponiendo que necesita operaciones que también cambian).
¿Qué tal boost :: vector, que se acaba de introducir desde boost 1.48.0 en adelante. ¿Es seguro para subprocesos? Estado
Docs:
//! boost::container::vector is similar to std::vector but it's compatible
//! with shared memory and memory mapped files.
tengo varios subprocesos que llaman al mismo tiempo push_back() en un objeto compartido de std :: vector. ... Espero buscar soluciones existentes de subprocesos seguros para vector.
Eche un vistazo a concurrent_vector
en Intel's TBB. Estrictamente hablando, es bastante diferente de std::vector
internamente y no es totalmente compatible con API, pero aún así podría ser adecuado. Puede encontrar algunos detalles sobre su diseño y funcionalidad in the blogs of TBB developers.
- 1. std :: vector to boost :: python :: list
- 2. Iterar std :: vector múltiple
- 3. std :: vector, thread-safety, multi-threading
- 4. ¿Puede un std :: vector ser = 'd a otro std :: vector?
- 5. sizeof() std :: vector (C++)
- 6. std vector C++ - copia profunda o superficial
- 7. std :: vector insert() reasignación
- 8. Cómo inicializar boost :: random :: discrete_distribution usando std :: vector?
- 9. boost :: python: lista de Python a std :: vector
- 10. C++ std :: pair, std :: vector y memcopy
- 11. Cómo exportar std :: vector
- 12. std :: vector de funciones
- 13. ¿Cómo puedo serializar un std :: vector con boost :: serialization?
- 14. ¿Cómo puedo ordenar un std :: vector por los valores de un std :: vector diferente?
- 15. std :: list vs std :: vector iteration
- 16. std :: vector de std :: vectores de contigüidad
- 17. paso eficiente de std :: vector
- 18. CopyOnWriteArray o Vector
- 19. std :: merge fusionando dos std :: vector coredump
- 20. std :: elementos de vector inicializando
- 21. std :: vector redimensionar hacia abajo
- 22. std :: vector vs normal array
- 23. convert std: vector to NSArray
- 24. ¿Es seguro devolver un vector poblado con variables locales?
- 25. std :: vector versus std :: array en C++
- 26. ¿Cuál es la diferencia entre std :: set y std :: vector?
- 27. std :: vector <std::string> crash
- 28. Convertir std :: vector en matriz
- 29. Asignador personalizado en std :: vector
- 30. Obtener matriz desde std: vector
Esto tiene que ser un dup. Pero, no, ninguno de los contenedores estándar es seguro para subprocesos. – smparkes
Vea también: http://stackoverflow.com/questions/1999122/how-to-define-threadsafe – ergosys
No es un engaño, pero está relacionado: http://stackoverflow.com/questions/1099513/threadsafe-vector-class- for-c – ergosys