varios programacion metodos hilos ejecutar creación carrera c# arrays string thread-safety enumeration

programacion - ¿Qué es seguro para hilos(C#)?(Cuerdas, matrices,...?)



metodos de hilos c# (5)

Soy bastante nuevo en C # así que por favor tengan paciencia conmigo. Estoy un poco confundido con la seguridad del hilo. ¿Cuándo es seguro un hilo y cuándo no?

¿La lectura (solo lectura de algo que se inicializó antes) de un campo siempre es segura para subprocesos?

//EXAMPLE RSACryptoServiceProvider rsa = new RSACrytoServiceProvider(); rsa.FromXmlString(xmlString); //Is this thread safe if xml String is predifined //and this code can be called from multiple threads?

¿El acceso a un objeto desde una matriz o lista siempre es seguro para subprocesos (en caso de que use un bucle for para enumeración)?

//EXAMPLE (a is local to thread, array and list are global) int a = 0; for(int i=0; i<10; i++) { a += array[i]; a -= list.ElementAt(i); }

¿Es la enumeración siempre / siempre hilo seguro?

//EXAMPLE foreach(Object o in list) { //do something with o }

¿ Escribir y leer en un campo en particular puede resultar en una lectura dañada (la mitad del campo se cambia y la mitad aún no se modifica)?

Gracias por todas sus respuestas y tiempo.

EDITAR: Me refiero a si todos los subprocesos solo están leyendo y usando (no escribiendo o cambiando) el objeto. (excepto por la última pregunta donde es obvio que me refería a si los subprocesos leen y escriben). Porque no sé si el acceso simple o la enumeración son seguros para subprocesos.


¿La lectura (solo lectura de algo que se inicializó antes) de un campo siempre es segura para subprocesos?

El lenguaje C # garantiza que las lecturas y escrituras se ordenan constantemente cuando las lecturas y escrituras están en un solo hilo en la sección 3.10:

La dependencia de los datos se conserva dentro de un hilo de ejecución. Es decir, el valor de cada variable se calcula como si todas las declaraciones en el hilo se ejecutaran en el orden original del programa. Se conservan las reglas de orden de inicialización.

Los eventos en un sistema multiprocesador de multiproceso no necesariamente tienen un orden consistente bien definido en el tiempo entre sí. El lenguaje C # no garantiza que haya un orden consistente. Se puede observar que una secuencia de escrituras observadas por un subproceso está en un orden completamente diferente cuando se observa desde otro subproceso, siempre que no esté involucrado ningún punto de ejecución crítico.

Por lo tanto, la pregunta no tiene respuesta porque contiene una palabra indefinida. ¿Puede dar una definición precisa de lo que significa "antes" para usted con respecto a los eventos en un sistema multiprocesador y multiproceso?

El lenguaje garantiza que los efectos secundarios se ordenan solo con respecto a los puntos críticos de ejecución, y aun así, no ofrece ninguna garantía sólida cuando se trata de excepciones. De nuevo, para citar de la sección 3.10:

La ejecución de un programa de C # continúa de tal manera que los efectos secundarios de cada subproceso en ejecución se conservan en los puntos críticos de ejecución. Un efecto secundario se define como una lectura o escritura de un campo volátil, una escritura en una variable no volátil, una escritura en un recurso externo y el lanzamiento de una excepción. Los puntos críticos de ejecución en los que se debe conservar el orden de estos efectos secundarios son las referencias a campos volátiles, declaraciones de bloqueo y creación y terminación de hilos. [...] El orden de los efectos secundarios se conserva con respecto a las lecturas y escrituras volátiles.

Además, el entorno de ejecución no necesita evaluar parte de una expresión si puede deducir que el valor de esa expresión no se usa y que no se producen los efectos secundarios necesarios (incluidos los causados ​​por llamar a un método o acceder a un campo volátil). Cuando la ejecución del programa es interrumpida por un evento asíncrono (como una excepción lanzada por otro hilo), no se garantiza que los efectos secundarios observables sean visibles en el orden original del programa.

¿El acceso a un objeto desde una matriz o lista siempre es seguro para subprocesos (en caso de que use un bucle for para enumeración)?

¿Por "hilo seguro" quiere decir que dos hilos siempre observarán resultados consistentes al leer de una lista? Como se señaló anteriormente, el lenguaje C # ofrece garantías muy limitadas sobre la observación de los resultados al leer de las variables. ¿Puede dar una definición precisa de lo que significa "hilo seguro" para usted con respecto a la lectura no volátil?

¿Es la enumeración siempre / siempre hilo seguro?

Incluso en escenarios de un solo hilo, es ilegal modificar una colección al enumerarla. Ciertamente es inseguro hacerlo en escenarios multiproceso.

¿Escribir y leer en un campo en particular puede resultar en una lectura dañada (la mitad del campo se cambia y la mitad aún no se modifica)?

Sí. Lo remito a la sección 5.5, que dice:

Las lecturas y escrituras de los siguientes tipos de datos son atómicas: bool, char, byte, sbyte, short, ushort, uint, int, float y tipos de referencia. Además, las lecturas y escrituras de tipos de enumeración con un tipo subyacente en la lista anterior también son atómicas. No se garantiza que las lecturas y escrituras de otros tipos, incluidos long, ulong, double y decimal, así como las definidas por el usuario, sean atómicas. Aparte de las funciones de biblioteca diseñadas para ese propósito, no hay garantía de lectura-modificación-escritura atómica, como en el caso de incremento o decremento.


Bueno, generalmente asumo que todo es inseguro. Para un acceso rápido y sucio a objetos globales en un entorno con hilos, uso la palabra clave de bloqueo (objeto) . .Net tiene un extenso conjunto de métodos de sincronización como diferentes semáforos y otros.


Es diferente para diferentes casos, pero en general, la lectura es segura si todos los hilos están leyendo. Si alguno está escribiendo, ninguna lectura o escritura es segura a menos que se pueda hacer de forma atómica (dentro de un bloque sincronizado o con un tipo atómico).

No es definitivo que la lectura sea correcta; nunca se sabe lo que sucede debajo de las capillas; por ejemplo, es posible que un receptor necesite inicializar los datos en el primer uso (por lo tanto, escribir en campos locales).

Para Strings, estás de suerte, son inmutables, así que todo lo que puedes hacer es leerlos. Con otros tipos, tendrá que tomar precauciones para evitar que cambien en otros subprocesos mientras los está leyendo.


La lectura puede ser insegura para los subprocesos si hay algún subproceso que está escribiendo (si escriben en medio de una lectura, por ejemplo, se verán afectados con una excepción).

Si debes hacer esto, entonces puedes hacer:

lock(i){ i.GetElementAt(a) }

Esto forzará la seguridad de subprocesos en i (siempre que otros subprocesos intenten bloquear i de manera similar antes de que lo usen. Solo una cosa puede bloquear un tipo de referencia a la vez.

En términos de enumeración, me referiré a la MSDN:

The enumerator does not have exclusive access to the collection; therefore, enumerating through a collection is intrinsically not a thread-safe procedure. To guarantee thread safety during enumeration, you can lock the collection during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.


Un ejemplo de no seguridad de subprocesos: cuando varios subprocesos incrementan un entero. Puede configurarlo de manera que tenga un número predeterminado de incrementos. Sin embargo, lo que puedes observar es que el int no se ha incrementado tanto como pensabas. Lo que sucede es que dos subprocesos pueden incrementar el mismo valor del entero. Esto es solo un ejemplo de una gran cantidad de efectos que puede observar al trabajar con varios subprocesos.

PD

Un incremento seguro para subprocesos está disponible a través de Interlocked.Increment(ref i)