2009-08-08 6 views
18

Así que todos hemos visto la notificación que rosca en MSDN para muchos objetos disponibles genéricos:¿Qué hace que los miembros de la instancia sean inseguros frente a públicos estáticos?

"static (Shared en Visual Basic) de este tipo son seguros para subprocesos los miembros de instancias se garantiza que sea seguro para subprocesos. "

Mi pregunta es, ¿qué significa ser una variable de instancia frente a una estática pública que la hace insegura?

+3

La parte entre paréntesis es lo que causa confusión al leer, más bien léalo como: Los miembros * públicos estáticos * de este tipo son seguros para subprocesos. Esto significa que los miembros estáticos de este objeto Tipo son seguros para el hilo, no se refiere a un "Tipo público estático"; instancia que se declara en su código. –

Respuesta

13

Esto solo es cierto en general.

En general, los métodos estáticos son estáticos porque no dependen ni acceden a ningún dato definido por instancia al que otro hilo también podría acceder. En general, las únicas variables que utilizan (un método estático) son variables declaradas y vinculadas a la memoria estática de la clase en la que se implementa el método, no a la memoria asignada para el objeto (la instancia de la clase) creada para ese objeto . Un método estático no hace referencia ni puede hacer referencia a ninguna de esas variables. Si un método utiliza este tipo de variable de datos de instancia, vinculada a una instancia específica, no puede ser estática. Un método de instancia, por el contrario, accede a algún elemento de datos (propiedad o campo) de la instancia.

Si, otoh, un método estático accede a una propiedad estática o campo de la clase, es igualmente no seguro para hilos.

Hay cuatro condiciones necesarias para que una carrera sea posible.

  1. La primera condición es que hay ubicaciones de memoria accesibles desde más de un hilo. Típicamente, estas ubicaciones son variables globales/estáticas o la memoria de pila puede alcanzarse desde variables globales/estáticas.
  2. La segunda condición es que hay una propiedad (a menudo llamada invariante), que está asociada con estas ubicaciones de memoria compartida que deben ser verdaderas o válidas para que el programa funcione correctamente. Normalmente, la propiedad debe mantenerse como verdadera antes de que se produzca una actualización para que la actualización sea correcta.
  3. La tercera condición es que la propiedad invariante no se mantiene durante alguna parte de la actualización real. (Es transitoriamente inválido o falso durante alguna parte del proceso).
  4. La cuarta y última condición que debe ocurrir para que una carrera suceda es que otro subproceso accede a la memoria mientras el invariante está roto, lo que provoca un comportamiento incoherente o incorrecto.
8

Es el problema del estado. Lo que hace que los métodos sean inseguros para varios subprocesos es que no tienen acceso al estado compartido de una manera segura para subprocesos. Los métodos estáticos en general no tienen acceso al estado compartido y, por lo tanto, es menos probable que entren en este problema. Todavía es posible tener condiciones de carrera en métodos estáticos/compartidos si tocan datos estáticos pero en general no lo hacen los métodos estáticos.

+0

Quizás deberías enfatizar el hecho de que es solo 'en general' más. – Dykam

+0

@Dykam, sí, hice un bolé con esa parte para enfatizar – JaredPar

12

Nada incorporado hace estática más o menos diferente (re hilo de seguridad) de ejemplo, con excepción de:

  • métodos estáticos son a menudo sin estado métodos "puros funcionales", haciéndolos automáticamente flujos seguros
  • hay una clara expectativa de miembros estáticos a ser flujos seguros (ya que realmente no se puede controlar lo que cada hilo está haciendo a la vez) - por lo que es de esperar que cualquier método estático que podría riesgo de hilo de seguridad hacerse flujos seguros

Esto no es cierto para los métodos de instancia:

  • métodos de instancia normalmente acceden estado en esa instancia
  • no hay expectativas de seguridad de los subprocesos a menos que se haga explícito en la documentación

Por lo tanto, en general, se espera que el llame al gestiona seguridad de hilos en instancias.

Existen excepciones donde las instancias son seguras para subprocesos (generalmente para cosas que están profundamente relacionadas con el subprocesamiento, como una cola productor-consumidor), pero cualquier miembro estático que no sea seguro para subprocesos es un error.

+1

@marc, estoy humildemente en desacuerdo ... por no decir que eso no existe, pero nunca he tenido la expectativa de que los métodos estáticos sean seguros para subprocesos, ni he oído hablar de tal expectativa. Los métodos estáticos aún pueden acceder a variables estáticas (de cualquier clase), así como a variables de instancia en objetos pasados ​​como parámetros de método. –

+0

(cont) La única forma en que se puede confiar en su expectativa es si se prohibió a todos los métodos estáticos utilizar cualquier variable de referencia por referencia pasada, o instancias de tipos de referencia, y acceder a cualquier variable estática en esa clase o en cualquier otra. Esto parecería ser una restricción extraordinariamente onerosa, solo para permitir que su "expectativa" sea confiable. –

+0

Tu razonamiento no sigue. Estoy hablando de su propio estado estático (como un diccionario/lista estática en un campo estático, utilizado por el método estático), ya que no puede ser controlado por la persona que llama. Normalmente, los métodos estáticos son seguros para subprocesos mediante el simple truco de no usar ningún estado privado ;-p El estado de cosas como 'ref' o ref-type args * es * controlado por la persona que llama, y ​​debe ser administrado como tal. Tampoco afecta las llamadas externas. La expectativa ** es ** allí, de lo contrario tendrías un ** lote ** de bloqueo en casi todas las líneas de tu código C#. –

0

El problema con los métodos que no son seguros para subprocesos es el acceso simultáneo a los recursos compartidos, como las variables de instancia. Si un método estático solo funciona en datos privados/locales, es intrínsecamente seguro para la ejecución de subprocesos. Sin embargo, no hay garantía de que los métodos estáticos lo hagan, esto debe hacerse explícitamente.

Así, para que un método estático sea seguro para hilos, no puede acceder a los miembros estáticos sin utilizar la sincronización y debe copiar los datos que recibe como entrada antes de modificarlos.

+0

¿Por qué son seguros los datos privados estáticos para métodos estáticos? – Dykam

+0

No estoy hablando de miembros privados como privados, pero privados como locales. Debido a que cada subproceso tiene su propia pila donde se almacenan las configuraciones regionales, estas no se comparten entre diferentes subprocesos y, por lo tanto, son intrínsecamente seguras para subprocesos. –

0

TLDR; "¿Esto significa que los métodos estáticos son intrínsecamente seguros para subprocesos? La respuesta es no. Las clases con la nota anterior tendrán métodos estáticos seguros para subprocesos porque los ingenieros de Microsoft escribieron el código de manera segura, quizás utilizando bloqueos u otros mecanismos de sincronización de subprocesos" (cita tomada de http://odetocode.com/Articles/314.aspx)

Más detalles

¿Qué es? Nada, excepto el código escrito para esa clase en particular.

La declaración es una declaración que le dice que los programadores que escribieron la clase se han asegurado de que todos los miembros estáticos (métodos y propiedades) son seguros para subprocesos (pero no lo han hecho por ejemplo miembros).

Se han asegurado de que la estática sea segura para subprocesos porque, al ser estática, es muy probable que reciban varios hilos de llamada, por lo que realizan el trabajo adicional necesario para asegurarse de que todo esté correcto. A menudo, los métodos estáticos también son funciones sin estado, lo que significa que ya son generalmente seguros para subprocesos (no se necesita trabajo adicional).

Por el contrario, para los miembros de la instancia, la declaración es simplemente que les dicen que no han sido tan cuidadosos con ellos.

A menudo, las instancias se crearán con un solo subproceso y solo se accederá a través de ese subproceso; si nunca se accede a la instancia por varios hilos, entonces la seguridad del hilo no es un problema, por lo que los programadores no se molestaron en agregarlo.

La declaración no es una afirmación acerca de las propiedades inherentes de la instancia estática frente a la instancia; ambos pueden ser inseguros a menos que ingrese un código específico para garantizar que múltiples hilos puedan acceder a ellos sin problemas (o si por naturaleza ya están seguros para hilos, por ejemplo, una función sin estado).

Es simplemente una declaración de que los programadores que escribieron esas clases se han asegurado de que los miembros estáticos son seguros, pero no lo han hecho, por ejemplo, los miembros.

Cuestiones relacionadas