2012-03-01 13 views
12

Soy consciente del hecho de que los contenedores de la biblioteca estándar no son seguros para subprocesos. Por eso solía pensar que un contenedor, digamos de tipo std::list, no puede accederse por más de un hilo al mismo tiempo (algunos de los cuales pueden modificar el contenedor). Pero ahora parece que hay más de lo que parece; algo más sutil, algo no tan obvio, al menos para mí.contenedores estándar como variables locales en la aplicación de subprocesos múltiples

Por ejemplo, considere esta función que acepta el primer argumento por valor :

void log(std::string msg, severity s, /*...*/) 
{ 
    return; //no code! 
} 

¿Este thread-safe?

Al principio, parece que es seguro para subprocesos, ya que el cuerpo de la función no tiene acceso a recursos modificables, por lo tanto, seguro para subprocesos. Pensándolo bien, se trata de mí que al invocar una función de este tipo, un objeto de tipo std::string será creado, que es el primer argumento, y creo que la construcción de este objeto no es hilo de seguridad, ya que utiliza internamente std::allocator , que creo que no es seguro para subprocesos. Por lo tanto, invocar dicha función tampoco es seguro para subprocesos. Pero si es correcto, ¿qué pasa con esto:

void f() 
{ 
    std::string msg = "message"; //is it thread-safe? it doesn't seem so! 
} 

¿Estoy yendo bien? ¿Podemos usar std::string (o cualquier contenedor que usa std::allocator internamente) en un programa de subprocesos múltiples?

Estoy hablando específicamente acerca de los contenedores como variables locales, a diferencia de los objetos compartidos.

busqué Google y encontró muchas dudas similares, sin respuesta concreta. Me enfrento a un problema similar al suyo:

Por favor considere C++ y C++ 03 11, ambos.

+0

Nawaz - ¿sabes qué implementación de C++ están hablando aquí: http://www.sgi.com/tech/stl/Allocators.html Indica que el asignador predeterminado es seguro para la rosca. – Sid

+0

@Sid: no es una biblioteca estándar; admiten muchas cosas que stdlib no tiene. – Nawaz

+0

Bien, perdón por la distracción. – Sid

Respuesta

7

En C++ 11, std::allocator es seguro para subprocesos. A partir de su definición:

20.6.9.1/6: Observación: el almacenamiento se obtiene llamando ::operator new(std::size_t)

y de la definición de ::operator new:

18.6.1.4: las versiones de la biblioteca de operator new y operator delete, versiones de sustitución de usuario de mundial operator new y operator delete, y el functi biblioteca estándar C ons calloc, malloc, realloc, y free se no introducir razas de datos (1.10) como resultado de llamadas simultáneas de diferentes hilos.

C++ 03 no tenía ningún concepto de hilos, por lo que cualquier seguridad de hilo era específica de la implementación; Tendría que consultar la documentación de su implementación para ver qué garantías ofrece, si corresponde.Dado que está utilizando la implementación de Microsoft, this page dice que es seguro escribir en varios objetos contenedor de la misma clase desde muchos hilos, lo que implica que std::allocator es seguro para subprocesos.

+0

Es C++ 11. ¿Qué hay de C++ 03? C++ 03 no tenía ningún concepto de multihilo. – Nawaz

+0

Bueno, busqué C++ 03, y parece que el asignador de C++ 03 no es seguro para subprocesos. – Nawaz

+0

@Nawaz: De hecho, C++ 03 no dice nada sobre seguridad de subprocesos, por lo que tendrá que consultar la documentación de su compilador/biblioteca. –

5

en C++ 11 esto sería dirigida por el asignador predeterminada en:

20.6.9.1 miembros asignador [allocator.members]

Excepto por el destructor, las funciones de miembros de la asignador predeterminado no introducirá carreras de datos (1.10) como resultado de llamadas concurrentes a esas funciones miembro de diferentes hilos. Las llamadas a estas funciones que asignan o desasignan una unidad particular de almacenamiento se producirán en un único pedido total, y cada una de estas llamadas de desasignación se realizará antes de la siguiente asignación (si corresponde) en este orden.

Cualquier asignador proporcionado por el usuario tendría que mantener las mismas limitaciones si se va a utilizar en diferentes subprocesos.

Por supuesto, para las versiones anteriores de la norma, no se dice nada de esto ya que no hablaban de multihilo. Si una implementación fuera compatible con multihilo (como muchos o la mayoría lo hacen), sería responsable de resolver esos problemas. Similar a la forma en que las implementaciones proporcionan un hilo seguro malloc() (y otras funciones de la biblioteca) para C y C++, aunque los estándares anteriores a muy recientemente no dicen nada al respecto.

3

Como ya habrá pensado, no habrá una respuesta fácil de sí o no. Sin embargo, creo que esto puede ayudar a:

http://www.cs.huji.ac.il/~etsman/Docs/gcc-3.4-base/libstdc++/html/faq/index.html#5_6

cito textualmente:

5,6 Is libstdC++ - v3 flujos seguros?

libstdC++ - v3 se esfuerza por ser thread-safe cuando todos los condiciones siguientes se cumplen: libc

del sistema es en sí mismo thread-safe, gcc -v informa de un modelo de subproceso distinto 'single', [pre-3.3 solamente] existe una implementación no genérica de atomicity.h para la arquitectura en cuestión.

+0

Se trata de una implementación particular de lib en un compilador muy antiguo ... 1 –

+0

@ DavidRodríguez-dribeas Creo que la mayoría de las respuestas que encontraremos a esta pregunta dependerán de qué compilador/versión de C++ y qué implementación de malloc es siendo utilizado. – Sid

2

Cuando un std::string se copia durante la llamada a log, el asignador puede ser thread-safe (obligatorio en C++ 11), pero la copia no lo es. Entonces, si hay otro hilo que muta la cadena fuente mientras se realiza la copia, esto no es seguro para subprocesos.

Puede terminar con la mitad de la cadena como antes de la mutación y otra mitad después, o incluso acceder a la memoria desasignada si reasigna el hilo mutante (por ejemplo, al agregar nuevos caracteres) o elimina la cadena, mientras la copia todavía estaba teniendo lugar.


otoh, la ...

std::string msg = "message"; 

...es seguro para subprocesos siempre que su asignador sea seguro para subprocesos.

+0

"* Entonces, si hay otro hilo que muta la cadena de origen mientras se realiza la copia, esto no es seguro para hilos. *". Ese es un problema diferente. No hablo de eso, ya que en este caso el problema radica en la lectura del objeto compartido, mientras hablo de objetos locales. – Nawaz

+1

@Nawaz Entonces todo el problema se reduce a la seguridad de subprocesos de su asignador, porque esto es lo único que se comparte entre subprocesos. –

Cuestiones relacionadas