2009-09-01 44 views
30

Tengo una pregunta sobre la seguridad del hilo de std :: set.¿El C++ std :: set es seguro para subprocesos?

Por lo que sé, puedo iterar sobre un conjunto y agregar/borrar miembros y eso no invalida los iteradores.

Pero considere siguiente escenario:

  • rosca 'A' itera sobre un conjunto de shared_ptr < tipo>
  • hilo de 'B' de vez en cuando 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?

Respuesta

9

Ninguno de los contenedores STL es seguro para subprocesos, por lo que std::set en particular no lo es.

En su caso, el problema no es ni siquiera realmente la seguridad de subprocesos: simplemente comparte un objeto a través de múltiples hilos (finos) y lo modifica en un hilo (bien también). Pero como ya dijiste, modificar el contenedor invalida sus iteradores. Si esto ocurre 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.

+9

actualizar un conjunto no invalida los iteradores ..... –

+0

En realidad, el estándar indica que agregar o eliminar de un conjunto std :: no invalida ninguno de sus iteradores (con iteradores apuntando a un objeto para ser eliminado siendo la excepción obvia). – suszterpatt

+0

Gracias por el comentario, lo fallé por completo. Aunque tengo que decir que, desde el punto de vista de un implementador, este es un requisito realmente extraño. –

26

STL no tiene soporte integrado para subprocesos, por lo que deberá extender el código STL con sus propios mecanismos de sincronización para usar STL en en un entorno multiproceso.

Por ejemplo vistazo aquí: link text

Desde conjunto es una clase de contenedor de MSDN ha siguiente que decir acerca de la seguridad de los subprocesos de los contenedores.

Un único 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 subproceso solo se escribe en un subproceso, todas las lecturas y escrituras en ese objeto en el mismo subproceso u otros hilos deben estar protegidos. 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 aunque sea otro el 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 la secuencia 1 y B se lee en la secuencia 2.

+8

En realidad, le resultará más fácil crear una clase segura para subprocesos que contenga un conjunto estándar en lugar de extender el conjunto. MANERA menos trabajo. – Kieveli

+4

@Kieveli +1, pero debe tener cuidado de no proporcionar puertas traseras en el conjunto (devolver iteradores de conjunto) y eso puede implicar tener que escribir su propio conjunto de iteradores encima de los iteradores establecidos para que los incrementos/decrementos sean seguros para subprocesos . Ni implementar un conjunto seguro de subprocesos ni un envoltorio son tareas simples ... –

+0

¿Puede proporcionar el enlace a la cita de MSDN? NEVERMIND: http://msdn.microsoft.com/en-us/library/c9ceah3b(v=VS.100).aspx –

19

La documentación de STL de Dinkumware 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 contenedores definidos en la biblioteca estándar de C++, con STL contenedores y objetos de plantilla basic_string clase, este aplicación sigue los ampliamente prácticas adoptadas enunciados de SGI STL:

Múltiples hilos pueden leer con seguridad el mismo objeto contenedor. (Hay subobjetos mutables nunprotected dentro un objeto contenedor.)

dos hilos pueden manipular de forma segura objetos recipiente diferente del mismo tipo. (No hay desprotegidos objetos estáticos compartidos dentro de un tipo de contenedor.)

Debe protegerse contra el acceso simultáneo a un objeto contenedor si al menos un hilo es la modificación del objeto. (Los primitivas de sincronización obvias, tales como los de la Biblioteca Dinkum Hilos, no serán subvertido por el objeto contenedor .)

Por lo tanto, no se hace ningún intento de asegurar que las operaciones atómicas sobre contenedor objetos son a salvo de amenazas; pero es lo suficientemente fácil como para hacer contenedores objetos que son seguros para hilos en el nivel de granularidad .

1

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 propios iteradores. Es cuando necesitan las estructuras de datos del contenedor para encontrar la posición en la que te metes en problemas.

Simple como eso.

0

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.

0

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 inválida), lo que lleva a un fallo de segmento.

Cuestiones relacionadas