¿Los métodos de IEnumerable Linq son seguros para subprocesos?

Me pregunto si los métodos de extensión Linq son atómicos. ¿O necesito lock cualquier objeto IEnumerable utilizado en los hilos, antes de cualquier tipo de iteración?

¿Decir que la variable es volatile tiene algún efecto sobre esto?

En resumen, ¿cuál de las siguientes opciones es la mejor operación segura para hilos?

1- Sin ningún locking:

 IEnumerable _objs = //... var foo = _objs.FirstOrDefault(t => // some condition 

2- Incluye instrucciones de locking:

 IEnumerable _objs = //... lock(_objs) { var foo = _objs.FirstOrDefault(t => // some condition } 

3- Declarar la variable como volátil:

 volatile IEnumerable _objs = //... var foo = _objs.FirstOrDefault(t => // some condition 

La interfaz IEnumerable no es segura para subprocesos. Consulte la documentación en http://msdn.microsoft.com/en-us/library/s793z9y2.aspx , que indica:

Un enumerador sigue siendo válido siempre que la colección permanezca sin cambios. Si se realizan cambios en la colección, como agregar, modificar o eliminar elementos, el enumerador queda irrevocablemente invalidado y su comportamiento no está definido.

El enumerador no tiene acceso exclusivo a la colección; por lo tanto, enumerar a través de una colección no es intrínsecamente un procedimiento seguro para subprocesos. Para garantizar la seguridad del subproceso durante la enumeración, puede bloquear la recostackción durante toda la enumeración. Para permitir que la colección sea accedida por múltiples hilos para lectura y escritura, debe implementar su propia sincronización.

Linq no cambia nada de esto.

El locking obviamente se puede usar para sincronizar el acceso a los objetos. Sin embargo, debe bloquear el objeto en cualquier lugar al que acceda, no solo al iterar sobre él.

Declarar que la colección es volátil no tendrá ningún efecto positivo. Solo da como resultado una barrera de memoria antes de una lectura y después de una escritura de la referencia a la colección. No sincroniza la lectura o escritura de la colección.

En resumen, no son seguros para subprocesos como se mencionó anteriormente.

Sin embargo, eso no significa que debe bloquear antes de “cada tipo de iteración”.

Debe sincronizar todas las operaciones que cambian la colección (agregar, modificar o eliminar elementos) con otras operaciones que (agregar, modificar, eliminar elementos o leer elementos).

Si solo está realizando operaciones de lectura en la colección al mismo tiempo, no se necesita locking. (por lo que ejecutar comandos LINQ como Average, Contains, ElementAtOrDefault todos juntos estaría bien)

Si los elementos en la colección son de longitud de palabra de máquina, como Int en la mayoría de las computadoras de 32 bits, entonces el cambio del valor de ese elemento ya se realiza atómicamente. En este caso, no agregue ni elimine elementos de la colección sin bloquearlos, pero modificar los valores puede ser correcto, si puede tratar con algo de no determinismo en su diseño.

Por último, puede considerar el locking detallado en elementos individuales o secciones de la colección, en lugar de bloquear toda la colección.

    Intereting Posts