2011-03-21 14 views
5

Me gustaría obtener un resumen de qué es exactamente seguro para subprocesos en C++ tanto según el estándar actual y C++ 0x como en la práctica (en general, pero también en mi caso con gcc 4.5.1)C++ Resumen de seguridad de subprocesos

Para contenedores STL, tengo entendido que la seguridad del hilo no está garantizada de acuerdo con la norma actual. ¿Es cierto, sin embargo, que en la práctica son seguras para subprocesos para un solo escritor, uso múltiple de lectores (en gcc y probablemente en la mayoría de los compiladores modernos)? ¿Esto está garantizado por C++ 11 ?.

¿Qué hay de los tipos de POD? Sé que el estándar no garantiza nada, pero me han dicho que, en la práctica, todos son seguros para leer y escribir. Por supuesto, incluso algo simple como el operador de incremento puede necesitar sincronización ya que podría haber múltiples lecturas y escrituras.

Estoy interesado principalmente en las respuestas, pero el por qué detrás de las respuestas sería apreciado.

+1

No existe el concepto de "subprocesos" o "seguridad de subprocesos" en el estándar actual de C++. –

+1

Las preguntas sobre seguridad de hilos como esta, sin ninguna especificación de lo que quiere decir con "hilo seguro" son esencialmente imposibles de responder. Lectura obligatoria: [¿Qué es lo que llamas "hilo seguro"] (http://blogs.msdn.com/b/ericlippert/archive/2009/10/19/what-is-this-thing-you-call- thread-safe.aspx). –

+0

@David: gran artículo, gracias :) –

Respuesta

1

La norma actual no menciona el enhebrado en absoluto, en ningún aspecto. En la práctica, los contenedores estándar proporcionan una lectura segura de subprocesos, pero requieren sincronización para la escritura.

C++ 0x no habla mucho (¿nada?) Específicamente sobre contenedores con respecto a la seguridad/intercambio de hilos, pero sí sobre asignaciones y cosas por el estilo. Al final, sale casi igual: aunque el objeto esté en un contenedor, estás leyendo/escribiendo datos, y tienes que sincronizar cuándo/si al menos un hilo puede modificar los datos.

Los datos POD en realidad no cambian demasiado: las modificaciones requerirán sincronización como regla general. Generalmente hay un subconjunto de tipos de datos para los cuales las operaciones son normalmente atómicas, pero los miembros de ese subconjunto varían según la plataforma. Normalmente incluirá tipos hasta el tamaño de palabra nativo del hardware asignado con alineación "natural"; cualquier otra cosa está abierta a muchas más preguntas.

+0

C++ 0x introduce 'std :: atomic' aunque, dado su nombre, creo que aquí hay un cierto grado de seguridad de hilos. ¿No es así? –

+0

@Matthieu M .: Sí, C++ 0x agrega bastante en el camino de las operaciones atómicas y mutexes. Éstos le permitirán sincronizar el acceso a un contenedor de forma portátil, pero ninguno de los contenedores se sincroniza automáticamente (al menos hasta donde recuerdo). –

+0

No creo que los contenedores estén sincronizados tampoco. Me parece recordar una garantía de que las operaciones de lectura no los modificarían (no Splay Tree aquí), pero eso es todo. –

0

POD y los tipos definidos estándar no tienen ningún hilo de seguridad. Depende exclusivamente del usuario del código sincronizar sus hilos para garantizar que no ocurra nada malo.

En C++ 0x, tengo poca idea; realmente no está revisando esa área del Estándar.

6

Ninguna de las cosas que ha mencionado son seguras para subprocesos, ni de forma estándar ni en la práctica.

La razón por la que los estándares no obligan a la seguridad del hilo es que la seguridad del hilo tiene un costo inherente. En general, C++ intenta no darte cosas que no solicites. Si quieres seguridad de hilo, entonces tienes que construirlo tú mismo. Esto es cierto incluso en C++ 0x, que incluye varias primitivas de sincronización.

Las razones por las que estas cosas no son seguras para hilos en la práctica son variadas. En general, los contenedores STL no son seguros para subprocesos porque cada una de sus operaciones básicas de actualización requiere múltiples pasos. Si un hilo intenta leer o actualizar un contenedor mientras otro hilo está en proceso de actualización, el contenedor estará en un estado indeterminado y, por lo tanto, los resultados serán impredecibles.

En el caso de los tipos de POD, las lecturas y escrituras también pueden tomar varios pasos para completarse. Este ejemplo más simple es un entero de 64 bits en una máquina de 32 bits. Se necesitan al menos dos instrucciones para leer o establecer el valor. Una vez más, esto significa que si un hilo intenta leer o actualizar el valor mientras otro hilo está en proceso de actualización, los resultados serán impredecibles.

0

Ni C ni C++ tienen primitivas de concurrencia incorporadas en el lenguaje en la forma (por ejemplo) que java tiene con synchronised. Esto es (creo) deliberado, incluso en las versiones modernas, para evitar tener los gastos generales cuando no es necesario. Unix no admitía procesos livianos en los primeros días, por lo que el enhebrado era en gran parte un problema del núcleo.

Diversas bibliotecas de hebras de propiedad (por ejemplo, hilos Solaris) fueron producidos por los vendedores, y la industria en última instancia estandarizadas en la biblioteca pthread, inicialmente con un modelo de subprocesamiento puramente espacio de usuario (bloqueo de llamadas como I/O bloquearía todas las discusiones) y más tarde con soporte de hilo kernel. Windows, OS/2 y varios otros sistemas operativos ofrecían instalaciones propietarias de hilos.

C/C++ están diseñados para ejecutarse en sistemas que pueden tener o no soporte de subprocesos y para funcionar de manera eficiente, por lo que el soporte de subprocesos es un extra opcional. Una de las filosofías de diseño de C++ es que el programador no debería tener que pagar por las características que no usa. Uno podría argumentar los méritos de este enfoque en una era de máquinas con núcleo múltiple, pero asumir 'the entire world is a PC' ha sido considerado un gran escollo al escribir el código C portátil desde hace algunas décadas.

El efecto neto es que el subprocesamiento tiende a ser específico de la plataforma, aunque existen bibliotecas de subprocesamiento multiplataforma.

Cuestiones relacionadas