c++ - ejemplo - std set count
Es C++ std:: set thread-safe? (6)
Explicación simple: si el hilo A mueve los iteradores a través del contenedor, está mirando el interior del contenedor. Si el hilo B modifica el contenedor (incluso una operación que no invalide el iterador que tiene A), el hilo A puede tener problemas porque B está engañando con el contenedor interno, posiblemente teniendo un estado (temporalmente) inválido. Esto causa bloqueos en el hilo A.
El problema NO son los iteradores mismos. Es cuando necesitan las estructuras de datos del contenedor para encontrar la posición en la que te metes en problemas.
Simple como eso.
Tengo una pregunta sobre la seguridad del hilo de std :: set.
Por lo que sé, puedo iterar sobre un conjunto y agregar / borrar miembros y eso no invalida los iteradores.
Pero considera el siguiente escenario:
- el hilo ''A'' itera sobre un conjunto de shared_ptr <Type>
- el hilo ''B'' ocasionalmente agrega elementos a este conjunto.
He experimentado segfaults mientras el programa se ejecuta y no estoy seguro de por qué sucede esto. ¿Es la falta de seguridad del hilo la causa?
La documentación de Dinkumware STL contiene el siguiente párrafo sobre ese tema. Es probable (como se indica en el texto) válido para la mayoría de las implementaciones.
Para los objetos de contenedor definidos en la biblioteca estándar de C ++, como STL Containers y objetos de la clase de plantilla basic_string, esta implementación sigue las prácticas ampliamente adoptadas explicadas para SGI STL:
Múltiples hilos pueden leer con seguridad el mismo objeto contenedor. (Hay subobjetos mutables no protegidos dentro de un objeto contenedor).
Dos hilos pueden manipular con seguridad diferentes objetos de contenedor del mismo tipo. (No hay objetos estáticos compartidos sin protección dentro de un tipo de contenedor).
Debe protegerse contra el acceso simultáneo a un objeto contenedor si al menos un hilo está modificando el objeto. (Las primitivas de sincronización obvias, como las de la Biblioteca de subprocesos Dinkum, no serán subvertidas por el objeto contenedor).
Por lo tanto, no se intenta garantizar que las operaciones atómicas en objetos contenedores sean seguras para hilos; pero es bastante fácil hacer objetos contenedores compartidos que son seguros para subprocesos en el nivel apropiado de granularidad.
La realización de una inserción puede hacer que el vector reasigne su memoria subyacente, mientras que el iterador aún puede apuntar a la dirección de memoria anterior (pero no válida), lo que lleva a la falla del segmento.
Sí. Una forma de manejar esta situación es hacer que cada thread bloquee un mutex compartido antes de acceder al mismo objeto set. Asegúrese de utilizar técnicas RAII para bloquear y desbloquear el mutex.
STL no tiene soporte de subprocesos incorporado, por lo que deberá extender el código STL con sus propios mecanismos de sincronización para usar STL en un entorno multiproceso.
Por ejemplo, mira aquí: enlace de texto
Como set es una clase contenedora, MSDN tiene lo siguiente para decir sobre la seguridad de los hilos de los contenedores.
Un solo objeto es seguro para la lectura de subprocesos múltiples. Por ejemplo, dado un objeto A, es seguro leer A desde el hilo 1 y desde el hilo 2 simultáneamente.
Si un solo hilo se escribe en un hilo, todas las lecturas y escrituras en ese mismo objeto u otros hilos deben estar protegidas. Por ejemplo, dado un objeto A, si el hilo 1 está escribiendo en A, entonces se debe evitar que el hilo 2 lea o escriba en A.
Es seguro leer y escribir en una instancia de un tipo incluso si otro hilo está leyendo o escribiendo en una instancia diferente del mismo tipo. Por ejemplo, dados los objetos A y B del mismo tipo, es seguro si A se escribe en el hilo 1 y B se lee en el hilo 2.
Ninguno de los contenedores STL es seguro para subprocesos, por lo que std::set
en particular no lo es.
Sin embargo, en su caso, el problema no es realmente la seguridad de las hebras: simplemente comparte un objeto a través de múltiples hilos (finos) y lo modifica en un hilo (también está bien). Pero como ya dijiste, modificar el contenedor invalida sus iteradores. Si esto sucede en el mismo subproceso o en un subproceso diferente no tiene ninguna consecuencia ya que sigue siendo el mismo contenedor .
D''oh! El §23.1.2.8 establece que la inserción no invalida los iteradores.