thread safe practice lock español best c# thread-safety

c# - practice - ¿Qué hace un método Thread-safe? ¿Cuales son las normas?



thread safe c# (4)

¿Existen reglas / directrices generales para lo que hace que un método sea seguro para subprocesos? Entiendo que probablemente haya un millón de situaciones excepcionales, pero ¿y en general? ¿Es esto simple?

  1. Si un método solo accede a las variables locales, es seguro para subprocesos.

¿Es asi? ¿Eso se aplica también a los métodos estáticos?

Una respuesta, proporcionada por @Cybis, fue:

Las variables locales no se pueden compartir entre subprocesos porque cada subproceso tiene su propia pila.

¿Ese es el caso de los métodos estáticos también?

Si se pasa un método a un objeto de referencia, ¿eso rompe la seguridad del hilo? Investigué un poco, y hay muchos por ahí sobre ciertos casos, pero esperaba poder definir, mediante el uso de unas pocas reglas, pautas a seguir para asegurarme de que un método sea seguro para subprocesos.

Entonces, supongo que mi pregunta final es: "¿Hay una breve lista de reglas que definen un método seguro para subprocesos? En caso afirmativo, ¿qué son?"

EDITAR
Muchos puntos buenos se han hecho aquí. Creo que la verdadera respuesta a esta pregunta es: "No existen reglas simples para garantizar la seguridad de los hilos". Guay. Multa. Pero, en general , creo que la respuesta aceptada proporciona un buen y breve resumen. Siempre hay excepciones Que así sea. Puedo vivir con ello.


Si un método solo accede a las variables locales, es seguro para subprocesos. ¿Es asi?

Absolutamente no. Puede escribir un programa con una sola variable local a la que se accede desde un solo hilo que, sin embargo, no es seguro para la ejecución de los hilos:

https://.com/a/8883117/88656

¿Eso se aplica también a los métodos estáticos?

Absolutamente no.

Una respuesta, proporcionada por @Cybis, fue: "Las variables locales no se pueden compartir entre subprocesos porque cada subproceso tiene su propia pila".

Absolutamente no. La característica distintiva de una variable local es que solo es visible desde el ámbito local , no que esté asignada en el grupo temporal . Es perfectamente legal y posible acceder a la misma variable local desde dos hilos diferentes. Puede hacerlo utilizando métodos anónimos, lambdas, bloques iteradores o métodos asíncronos.

¿Ese es el caso de los métodos estáticos también?

Absolutamente no.

Si se pasa un método a un objeto de referencia, ¿eso rompe la seguridad del hilo?

Tal vez.

Investigué un poco, y hay muchos por ahí sobre ciertos casos, pero esperaba poder definir, mediante el uso de unas pocas reglas, pautas a seguir para asegurarme de que un método sea seguro para subprocesos.

Tendrás que aprender a vivir con decepción. Este es un tema muy difícil.

Entonces, supongo que mi pregunta final es: "¿Hay una breve lista de reglas que definen un método seguro para subprocesos?

Nop. Como viste anteriormente en mi ejemplo, un método vacío puede no ser seguro para subprocesos . También podría preguntar "¿hay una breve lista de reglas que garantice que un método sea correcto? ". No no hay. La seguridad del hilo no es más que un tipo de corrección extremadamente complicado.

Además, el hecho de que haga la pregunta indica su malentendido fundamental sobre la seguridad de la secuencia. La seguridad de subprocesos es una propiedad global , no local , de un programa. La razón por la que es tan difícil hacerlo bien es porque debe tener un conocimiento completo del comportamiento de subprocesamiento de todo el programa para garantizar su seguridad.

De nuevo, mira mi ejemplo: cada método es trivial . Es la forma en que los métodos interactúan entre sí a un nivel "global" que hace que el programa se estanque. No puede ver todos los métodos y marcarlos como "seguros" y luego esperar que todo el programa sea seguro, como tampoco puede concluir que debido a que su casa está hecha de ladrillos 100% no huecos, la casa también está no hueca El vacío de una casa es una propiedad global de todo, no un agregado de las propiedades de sus partes.



No hay una regla dura y rápida.

Aquí hay algunas reglas para hacer seguro el hilo del código en .NET y por qué estas no son buenas reglas:

  1. La función y todas las funciones que llama deben ser puras (sin efectos secundarios) y usar variables locales. Aunque esto hará que su código sea seguro para subprocesos, también hay muy pocas cosas interesantes que puede hacer con esta restricción en .NET.
  2. Cada función que opera en un objeto común debe lock en una cosa común. Todos los bloqueos deben hacerse en el mismo orden. Esto hará que el hilo del código sea seguro, pero será increíblemente lento, y también podría no utilizar múltiples hilos.
  3. ...

No existe una regla que asegure la seguridad del hilo del código, lo único que puede hacer es asegurarse de que su código funcione sin importar cuántas veces se esté ejecutando activamente, cada hilo se puede interrumpir en cualquier punto, con cada hilo en su propio estado / ubicación, y esto para cada función (estática o no) que está accediendo a objetos comunes.


Si un método (instancia o estática) solo hace referencia a variables dentro de ese método, entonces es seguro para subprocesos porque cada subproceso tiene su propia pila:

En este caso, varios hilos podrían llamar a ThreadSafeMethod simultáneamente sin problema.

public class Thing { public int ThreadSafeMethod(string parameter1) { int number; // each thread will have its own variable for number. number = parameter1.Length; return number; } }

Esto también es cierto si el método llama a otro método de clase que solo hace referencia a variables de ámbito local:

public class Thing { public int ThreadSafeMethod(string parameter1) { int number; number = this.GetLength(parameter1); return number; } private int GetLength(string value) { int length = value.Length; return length; } }

Si un método accede a propiedades o campos (de estado de objeto) (instancia o estática), entonces necesita usar bloqueos para asegurarse de que los valores no sean modificados por un hilo diferente.

public class Thing { private string someValue; // all threads will read and write to this same field value public int NonThreadSafeMethod(string parameter1) { this.someValue = parameter1; int number; // Since access to someValue is not synchronised by the class, a separate thread // could have changed its value between this thread setting its value at the start // of the method and this line reading its value. number = this.someValue.Length; return number; } }

Debe tener en cuenta que cualquier parámetro pasado al método que no sea ni struct ni inmutable podría ser mutado por otro hilo fuera del alcance del método.

Para garantizar una concurrencia adecuada, debe usar el bloqueo.

para obtener más información, consulte la instrucción de bloqueo C # reference y ReadWriterLockSlim .

el bloqueo es principalmente útil para proporcionar una funcionalidad a la vez,
ReadWriterLockSlim es útil si necesita varios lectores y escritores individuales.