c# - sm12 - ¿Por qué el objeto de bloqueo tiene que ser de solo lectura?
objetos de bloqueo (4)
Al implementar un bloqueo, solía crear un objeto privado dentro de mi clase:
Si quiero estar seguro de que está bloqueado en el hilo que creó mi clase:
private object Locker = new object();
Si quiero asegurarme de que estará bloqueado para todos los subprocesos dentro de mi aplicación:
private static object Locker = new object();
Pero aquí: ¿Por qué el objeto de bloqueo tiene que ser estático?
y en otras muchas preguntas, todos dicen que el objeto debe ser de readonly
. No he encontrado la razón, ni siquiera en MSDN o JavaDoc.
Como uso este tipo de construcción con bastante frecuencia, ¿podría alguien explicarme por qué debería usar readonly
?
¡Gracias!
Si quiero asegurarme de que estará bloqueado para todos los subprocesos dentro de mi aplicación:
El objeto de bloqueo debe ser estático, si bloquea el acceso al estado estático.
De lo contrario, tiene que ser una instancia, porque no es necesario bloquear el estado de una instancia de clase y evitar que otros subprocesos funcionen con otra instancia de clase al mismo tiempo.
todos dicen que el objeto tiene que ser "solo lectura" no encontré la razón
Bueno, no tiene que ser así. Esta es solo una buena práctica, que le ayuda a evitar errores.
Considere este código:
class MyClass
{
private object myLock = new object();
private int state;
public void Method1()
{
lock (myLock)
{
state = // ...
}
}
public void Method2()
{
myLock = new object();
lock (myLock)
{
state = // ...
}
}
}
Aquí Thread1 puede adquirir bloqueo a través del Method1
, pero Thread2, que ejecutará el Method2
, ignorará este bloqueo, porque el objeto de bloqueo se cambió => el estado puede estar dañado.
Lo ideal es que el objeto se lea solo para que no se pueda cambiar para que apunte a otro objeto. Si se bloquea un objeto, luego otro hilo cambia el objeto, si, entonces aparece otro hilo, y trata de bloquearlo, el objeto en cuestión no sería el mismo, por lo que el bloqueo original sería invalidado
Este sería un caso muy raro. Pero si tenía un bloqueo en el objeto y otro hilo en espera de ese objeto, si el hilo de bloqueo llama a Monitor.Pulse, el hilo en espera se ha despertado y puede bloquear el objeto. En ese período de tiempo entre ser despertado y tomar el bloqueo, otro hilo podría cambiar el objeto al que se hace referencia en el bloqueo, por lo que el hilo en espera tomaría un bloqueo en un objeto diferente.
No tiene que ser de solo lectura, pero es una buena práctica, ya que evita que la sustituyas accidentalmente, lo que puede llevar a algunos errores difíciles de localizar.
Supongo que lo que quería decir es "una variable que hace referencia a un objeto de bloqueo debe ser de solo lectura".
Bloquea un objeto de bloqueo al que hace referencia la variable, no a una variable en sí misma. Es decir, tener
private object Locker = new object();
bloquea ese nuevo objeto (), no en el campo Locker. Luego, si reemplaza el valor del campo con una referencia a otro objeto, diga
Locker = new object();
y bloquéelo, está bloqueando dos objetos diferentes , y eso anula el propósito del bloqueo, porque ahora no obtiene un acceso sincronizado.