C #: ¿Qué sucede si se llama a un método estático desde varios subprocesos?

93

En mi aplicación, tengo un método estático que se llama desde varios subprocesos al mismo tiempo. ¿Existe algún peligro de que se confundan mis datos?

En mi primer intento, el método no era estático y estaba creando varias instancias de la clase. En ese caso, mis datos se mezclaron de alguna manera. No estoy seguro de cómo sucede esto porque solo sucede a veces. Todavía estoy depurando. Pero ahora el método es estático y no tengo problemas hasta ahora. Quizás sea solo suerte. No estoy seguro.

TalkingCode
fuente

Respuestas:

96

Las variables declaradas dentro de los métodos (con la posible excepción de las variables " capturadas ") están aisladas, por lo que no obtendrá ningún problema inherente; sin embargo, si su método estático accede a cualquier estado compartido, todas las apuestas están canceladas.

Ejemplos de estado compartido serían:

  • campos estáticos
  • objetos a los que se accede desde un caché común (no serializado)
  • datos obtenidos a través de los parámetros de entrada (y el estado de esos objetos), si es posible que varios subprocesos estén tocando el mismo objeto (s)

Si tiene un estado compartido, debe:

  • tenga cuidado de no mutar el estado una vez que se pueda compartir (mejor: use objetos inmutables para representar el estado y tome una instantánea del estado en una variable local, es decir, en lugar de hacer referencia whatever.SomeDatarepetidamente, lee whatever.SomeData una vez en una variable local, y luego solo use la variable, tenga en cuenta que esto solo ayuda para el estado inmutable)
  • sincronizar el acceso a los datos (todos los subprocesos deben sincronizarse), ya sea mutuamente excluyente o (más granular) lector / escritor
Marc Gravell
fuente
1
@Diego: ¿ese comentario es para mí o para @Holli?
Marc Gravell
Para Holli, solo para agregar información práctica a su respuesta.
Diego Pereyra
1
@Marc No puedo estar completamente de acuerdo con "Las variables declaradas dentro de los métodos (con la posible excepción de las variables" capturadas ") están aisladas". Considere un identificador de archivo que se declara en un método estático. Entonces, un hilo puede acceder al mango cuando otro hilo lo usa. Conducirá a un comportamiento inesperado. ¿O su variable "capturada" también significa "identificador de archivo"?
prabhakaran
9
@prabhakaran si un identificador de archivo es una variable método, que está en el ámbito únicamente a la persona que llama. Cualquier otra persona que llame estará hablando con una variable diferente (las variables de método son por llamada). Ahora, el acceso al archivo subyacente es un problema independiente, pero no está relacionado con c # o .NET. Si el identificador no se comparte, uno esperaría algún tipo de mutex / bloqueo si este escenario es probable.
Marc Gravell
29

Sí, es solo suerte. ;)

No importa si el método es estático o no, lo que importa es si los datos son estáticos o no.

Si cada hilo tiene su propia instancia separada de la clase con su propio conjunto de datos, no hay riesgo de que se confundan los datos. Si los datos son estáticos, solo hay un conjunto de datos y todos los subprocesos comparten los mismos datos, por lo que no hay forma de no mezclarlos.

Cuando sus datos en instancias separadas todavía se confunden, es muy probable que los datos no estén realmente separados.

Guffa
fuente
7
Me encantó esa línea - It doesn't matter if the method is static or not, what matters is if the data is static or not. Solo para agregar, las variables locales declaradas dentro del alcance de un método estático no forman esa parte de los datos por la que debemos preocuparnos en el escenario dado.
RBT
gran respuesta. Ayudó mucho.
Fractal
15

Los métodos estáticos deberían estar bien para varios subprocesos.

Por otro lado, los datos estáticos podrían causar un problema porque los intentos de acceder a los mismos datos desde diferentes subprocesos deben controlarse para garantizar que solo un subproceso a la vez esté leyendo o escribiendo los datos.

Doug Ferguson
fuente
2
La palabra clave aquí es sincronización :-)
G. Stoynev
2
la lectura está bien para suceder al mismo tiempo, pero leer Y escribir al mismo tiempo conducirá a un comportamiento inesperado
Freestyle076
9

MSDN siempre dice:

Cualquier miembro público estático (compartido en Visual Basic) de este tipo es seguro para subprocesos. No se garantiza que ningún miembro de instancia sea seguro para subprocesos.

Editar: Como dicen los chicos aquí, no siempre es el caso, y claramente esto se aplica a las clases diseñadas de esta manera en el BCL, no a las clases creadas por el usuario donde esto no se aplica.

Marcote
fuente
3
¡Uf! Finalmente, entendí el significado de esta nota que se encuentra con tanta frecuencia en la documentación de MSDN. Entonces, básicamente, cuando MS diseña un método estático (donde se publica esta nota) en BCL, no acceden a ninguna variable / miembro / estado que esté fuera del alcance de ese método. Dependen completamente de las variables locales del ámbito del método solo para implementar la lógica de ese método. Muy contento de que lo hayas compartido.
RBT
@Marcote, ¿no es cierto lo contrario? Los miembros de la instancia son seguros porque hay uno por instancia. Sin embargo, los miembros estáticos no son seguros para subprocesos porque se comparten entre todas las instancias de esa clase. quora.com/…
Fractal
1
depende. Nunca trataría a un miembro de instancia de forma segura de forma predeterminada. Es por eso que un conjunto completo de bibliotecas y para evitar la corrupción de datos entre muchas otras cosas.
Marcote
1
bien, gracias @Marcote. Poco a poco me estoy dando cuenta de que tengo mucho que aprender.
Fractal