thread synlock lock example español async c# multithreading locking block critical-section

synlock - thread synchronization c#



Confusión sobre la declaración de bloqueo en C# (6)

Esto es de MSDN: la palabra clave de bloqueo garantiza que un subproceso no ingrese a una sección crítica de código mientras que otro subproceso está en la sección crítica .

¿ Una sección crítica tiene que ser igual que la sección crítica ?

O significa: la palabra clave de bloqueo garantiza que un subproceso no ingrese a ninguna sección crítica protegida por un objeto de código, mientras que otro subproceso está en una sección crítica protegida por el mismo objeto . ?

class Program { static void Main(string[] args) { TestDifferentCriticalSections(); Console.ReadLine(); } private static void TestDifferentCriticalSections() { Test lo = new Test(); Thread t1 = new Thread(() => { lo.MethodA(); }); t1.Start(); Thread t2 = new Thread(() => { lo.MethodB(); }); t2.Start(); } } public class Test { private object obj = new object(); public Test() { } public void MethodA() { lock (obj) { for (int i = 0; i < 5; i++) { Thread.Sleep(500); Console.WriteLine("A"); } } } public void MethodB() { lock (obj) { for (int i = 0; i < 5; i++) { Thread.Sleep(500); Console.WriteLine("B"); } } } }


Es una y la misma sección crítica.

lock (synclock) { // the critical section protected by the lock statement // Only one thread can access this at any one time }

Vea la declaración de bloqueo en MSDN:

La palabra clave de bloqueo marca un bloque de declaración como una sección crítica al obtener el bloqueo de exclusión mutua para un objeto determinado, ejecutar una declaración y luego liberar el bloqueo.

O significa: la palabra clave de bloqueo garantiza que un subproceso no ingrese a ninguna sección crítica del código mientras que otro subproceso está en una sección crítica. ?

No No significa eso. Significa la sección crítica protegida por ese bloqueo y ese bloqueo solo.

Actualización, siguiente ejemplo de código:

Si usa un solo objeto para bloquear, bloqueará todas las secciones críticas, lo que hará que otros hilos se bloqueen hasta que se liberen. En su ejemplo de código, una vez que se haya ingresado el bloqueo en el MethodA , todos los otros hilos que alcanzan ese bloqueo y el bloqueo en el MethodB se bloquearán hasta que se libere el bloqueo (esto sucede porque está bloqueando el mismo objeto en ambos métodos).


La pregunta está redactada de manera confusa y las respuestas hasta el momento tampoco son particularmente claras. Permítanme reformular la pregunta en varias preguntas:

(1) ¿La declaración de bloqueo garantiza que no haya más de un hilo en el cuerpo de la declaración de bloqueo a la vez?

No Por ejemplo:

static readonly object lock1 = new object(); static readonly object lock2 = new object(); static int counter = 0; static object M() { int c = Interlocked.Increment(ref counter); return c % 2 == 0 ? lock1 : lock2; } ... lock(M()) { Critical(); }

Es posible que dos hilos estén en el cuerpo de la instrucción de bloqueo al mismo tiempo, porque la instrucción de bloqueo se bloquea en dos objetos diferentes. Thread Alpha puede llamar a M () y obtener lock1, y luego thread Beta puede llamar a M () y obtener lock2.

(2) Suponiendo que mi declaración de bloqueo siempre se bloquee en el mismo objeto, ¿una declaración de bloqueo garantiza que no haya más de un hilo "activo" en el cuerpo del bloqueo a la vez?

Sí. Si usted tiene:

static readonly object lock1 = new object(); ... lock(lock1) { Critical(); }

luego el hilo Alpha puede tomar el bloqueo, y el hilo Beta se bloqueará hasta que el bloqueo esté disponible antes de ingresar al cuerpo del bloqueo.

(3) Suponiendo que tengo dos declaraciones de bloqueo, y que ambas declaraciones de bloqueo se bloquean en el mismo objeto cada vez, ¿una declaración de bloqueo garantiza que no haya más de un hilo "activo" en el cuerpo de cada bloqueo en un momento dado?

Sí. Si usted tiene:

static readonly object lock1 = new object(); ... static void X() { lock(lock1) { CriticalX(); } } static void Y() { lock(lock1) { CriticalY(); } }

luego, si el hilo Alfa está en X y toma el bloqueo, y el hilo Beta está en Y, entonces el hilo Beta se bloqueará hasta que el bloqueo esté disponible antes de ingresar al cuerpo del bloqueo.

(4) ¿Por qué colocas "activo" en "cotizaciones de miedo"?

Para llamar la atención sobre el hecho de que es posible que un hilo en espera esté en el cuerpo de la cerradura. Puede usar el método Monitor.Wait para "pausar" un hilo que está en un cuerpo de bloqueo, y permitir que un hilo bloqueado se active e ingrese ese cuerpo de bloqueo (o un cuerpo de bloqueo diferente que bloquee el mismo objeto). El hilo en espera permanecerá en su estado de "espera" hasta que se pulse. En algún momento después de que se pulsa, vuelve a unirse a la cola "listo" y se bloquea hasta que no hay un hilo "activo" en el bloqueo. Luego se reanuda en el punto donde se detuvo.


La sección crítica de la que se habla es la sección protegida por las declaraciones de bloqueo.

Cualquier sección crítica que se bloquee en el mismo objeto será bloqueada para que no tenga acceso.

También es importante que su objeto de bloqueo sea estático, ya que los bloqueos deben estar bloqueados (o tratando de bloquear) en la misma instancia del objeto de bloqueo.


No significa que ninguno , aunque puede proteger dos bloques de código para que no ingresen más de un hilo al mismo tiempo al bloquearlos con el mismo objeto. Este es un paradigma común: es posible que desee bloquear su colección para borrados y escrituras.


No, significa que otro subproceso no entrará en la sección crítica protegida por esta declaración de bloqueo.

La sección Crítica solo está definida por el programador, y en este caso, podría reemplazarla por: la sección protegida por un bloqueo

Traducción: la palabra clave de lock garantiza que un subproceso no ingrese a una sección de código protegida por un lock mientras que otro subproceso está en esta sección de código (protegido por un lock )


Pusiste un candado en un objeto. Si otro hilo intenta acceder a una sección crítica marcada por ese objeto al mismo tiempo, se bloqueará hasta que se elimine / complete el bloqueo.

Ejemplo:

public static object DatabaseLck= new object(); lock (DatabaseLck) { results = db.Query<T>(query).ToList(); }

O

lock (DatabaseLck) { results = db.Query<T>(string.Format(query, args)).ToList(); }

Ninguno de estos bloques de código puede ejecutarse al mismo tiempo PORQUE usan el mismo objeto de bloqueo. Si usó un objeto de bloqueo diferente para cada uno, podrían ejecutarse al mismo tiempo.