En general, asumo que las transmisiones no están sincronizadas, depende del usuario hacer el bloqueo apropiado. Sin embargo, ¿cosas como cout
recibir un tratamiento especial en la biblioteca estándar?
Es decir, si se escriben varios subprocesos, ¿ cout
pueden dañar el cout
objeto? Entiendo que incluso si estuviera sincronizado, todavía obtendría una salida intercalada aleatoriamente, pero ese intercalado está garantizado. Es decir, ¿es seguro utilizarlo cout
desde varios subprocesos?
¿Depende este proveedor? ¿Qué hace gcc?
Importante : proporcione algún tipo de referencia para su respuesta si dice "sí", ya que necesito algún tipo de prueba de esto.
Mi preocupación tampoco es sobre las llamadas al sistema subyacentes, están bien, pero las secuencias agregan una capa de almacenamiento en búfer en la parte superior.
printf
brilla, ya que la salida completa se escribe destdout
una vez; cuando el uso destd::cout
cada eslabón de la cadena de expresión se enviaría por separado astdout
; entre ellos puede haber algún otro hilo de escriturastdout
debido al cual el orden de la salida final se estropea.Respuestas:
El estándar C ++ 03 no dice nada al respecto. Cuando no tiene garantías sobre la seguridad de subprocesos de algo, debe tratarlo como no seguro para subprocesos.
De particular interés aquí es el hecho de que
cout
está protegido. Incluso siwrite
se garantiza que las llamadas a (o lo que sea que logre ese efecto en esa implementación en particular) sean mutuamente excluyentes, el búfer podría ser compartido por los diferentes subprocesos. Esto conducirá rápidamente a la corrupción del estado interno de la secuencia.E incluso si se garantiza que el acceso al búfer es seguro para subprocesos, ¿qué crees que sucederá en este código?
Probablemente desee que cada línea aquí actúe en exclusión mutua. Pero, ¿cómo puede garantizar eso una implementación?
En C ++ 11, tenemos algunas garantías. El FDIS dice lo siguiente en §27.4.1 [iostream.objects.overview]:
Por lo tanto, no obtendrá transmisiones dañadas, pero aún debe sincronizarlas manualmente si no desea que la salida sea basura.
fuente
cout.sync_with_stdio()
sea cierto, el usocout
para generar caracteres de varios subprocesos sin sincronización adicional está bien definido, pero solo en el nivel de bytes individuales. Por lo tanto,cout << "ab";
y se puedecout << "cd"
ejecutar en diferentes subprocesosacdb
, por ejemplo, pero no puede causar un comportamiento indefinido.Esta es una gran pregunta.
Primero, C ++ 98 / C ++ 03 no tiene el concepto de "hilo". Entonces, en ese mundo, la pregunta no tiene sentido.
¿Qué pasa con C ++ 0x? Vea la respuesta de Martinho (que admito que me sorprendió).
¿Qué hay de las implementaciones específicas anteriores a C ++ 0x? Bueno, por ejemplo, aquí está el código fuente
basic_streambuf<...>:sputc
de GCC 4.5.2 (encabezado "streambuf"):Claramente, esto no realiza ningún bloqueo. Y tampoco lo hace
xsputn
. Y este es definitivamente el tipo de streambuf que usa Cout.Por lo que puedo decir, libstdc ++ no bloquea ninguna de las operaciones de transmisión. Y no esperaría ninguno, ya que sería lento.
Entonces, con esta implementación, obviamente es posible que la salida de dos subprocesos se corrompa entre sí ( no solo se intercalen).
¿Podría este código dañar la estructura de datos en sí? La respuesta depende de las posibles interacciones de estas funciones; por ejemplo, qué sucede si un hilo intenta vaciar el búfer mientras otro intenta llamar
xsputn
o lo que sea. Puede depender de cómo el compilador y la CPU decidan reordenar las cargas y almacenes de memoria; se necesitaría un análisis cuidadoso para estar seguro. También depende de lo que haga su CPU si dos subprocesos intentan modificar la misma ubicación al mismo tiempo.En otras palabras, incluso si funciona bien en su entorno actual, podría romperse cuando actualice su tiempo de ejecución, compilador o CPU.
Resumen ejecutivo: "No lo haría". Cree una clase de registro que realice un bloqueo adecuado o muévala a C ++ 0x.
Como alternativa débil, puede configurar cout como sin búfer. Es probable (aunque no garantizado) que omita toda la lógica relacionada con el búfer y llame
write
directamente. Aunque eso podría ser prohibitivamente lento.fuente
cout
.www.techrepublic.com/article/use-stl-streams-for-easy-c-plus-plus-thread-safe-logging
y también: ¿Son los flujos de salida estándar en C ++ seguros para subprocesos (cout, cerr, clog)?
ACTUALIZAR
Por favor, eche un vistazo a la respuesta de @Martinho Fernandes para saber qué dice el nuevo estándar C ++ 11 sobre esto.
fuente
Como mencionan otras respuestas, esto definitivamente es específico del proveedor, ya que el estándar C ++ no menciona el subproceso (esto cambia en C ++ 0x).
GCC no hace muchas promesas sobre seguridad de subprocesos y E / S. Pero la documentación de lo que promete está aquí:
la clave es probablemente:
No sé si algo ha cambiado desde el período de tiempo 3.0 mencionado.
La documentación de seguridad de subprocesos de MSVC para
iostreams
se puede encontrar aquí: http://msdn.microsoft.com/en-us/library/c9ceah3b.aspx :Tenga en cuenta que esa información es para la versión más reciente de MSVC (actualmente para VS 2010 / MSVC 10 /
cl.exe
16.x). Puede seleccionar la información para versiones anteriores de MSVC mediante un control desplegable en la página (y la información es diferente para versiones anteriores).fuente