Obtener un bloqueo usando un objeto, en lugar de esto - Threading [duplicado]
Frecuentes
Visto 256 veces
3
Estoy tratando de aprender a enhebrar en C#, y he visto surgir algo en algunos artículos, pero no estoy seguro de entenderlo completamente: en los dos ejemplos dados, ¿cuál sería la diferencia fundamental entre obtener un bloqueo en 'esto'? vs 'thisLock'.
Ejemplo 1:
class Account
{
decimal balance;
private Object thisLock = new Object();
public void Withdraw(decimal amount)
{
lock (thisLock)
{
if (amount > balance)
{
throw new Exception("Insufficient funds");
}
balance -= amount;
}
}
}
Ejemplo 2:
class Account
{
decimal balance;
public void Withdraw(decimal amount)
{
lock (this)
{
if (amount > balance)
{
throw new Exception("Insufficient funds");
}
balance -= amount;
}
}
}
Según tengo entendido, pensaría que 'thisLock' solo evita que otros subprocesos ingresen a esa área específica del código.
Si obtener un bloqueo en 'esto' detendría todas las operaciones en el objeto, es decir, las llamadas a otros métodos por parte de otros subprocesos.
¿Fundamentalmente no he entendido esto, o es esa la conclusión correcta?
3 Respuestas
2
Ambos casos tendrán exactamente el mismo efecto. Una diferencia es que otros objetos no pueden ver thisLock
, por lo que puede estar seguro de que nada más reutilizará el bloqueo. si bloqueas this
, otra parte del código también puede bloquearse en la misma instancia de Cuenta.
Respondido el 03 de diciembre de 13 a las 13:12
"puede estar seguro de que nada más reutilizará el candado" - siempre que ningún otro método en esa clase use el mismo objeto de bloqueo. - CodeCaster
@CodeCaster: Por supuesto, pero esto es algo sobre lo que usted, como escritor de esa clase, tiene control total :-) - Steven
1
La diferencia es la granularidad de bloqueo.
Al bloquear un objeto, (simplificado) se establece un bit en la instancia. Cualquier otra persona que intente bloquear la misma instancia terminará en un estado de espera hasta que el otro libere el bloqueo.
En muchos casos, los métodos en un objeto se pueden usar al mismo tiempo (bajo en paralelo). Bloquear todo el objeto (esto) excluiría el uso de cualquier otro método si ese método también usa 'lock(this)
'.
Dado que el bloqueo se puede usar en cualquier tipo de referencia, podemos crear objetos de "bloqueo". Donde implementamos el 'lock(lockObject)
' sobre una base de exclusión.
Como ejemplo;
- MethodA1 y MethodA2 no se pueden usar al mismo tiempo
MethodB1 y MethodB2 no se pueden usar al mismo tiempo
El Método A1/2 se puede utilizar al mismo tiempo que el Método B1/2.
Si usáramos el lock(this)
en cada método, también excluiríamos que el Método A1/2 se ejecute al mismo tiempo que el Método B1/2.
Al crear 2 objetos de bloqueo (lockAMethods, lockBMethods), ahora podemos implementar nuestro bloqueo de manera más granular.
- En MethodA1 y MethodA2 usaremos "
lock(lockAMethods)
" para asegurarse de que los métodos A1 y A2 no se puedan ejecutar al mismo tiempo. - En MethodB1 y B2 usaremos el
"lock(lockBMethods)
" para asegurarse de que los métodos B1 y B2 no se puedan ejecutar al mismo tiempo.
Sin embargo, podemos lock(lockAMethods)
y lock(lockBMethods)
al mismo tiempo. Por lo tanto, ahora podemos ejecutar MethodA1/2 al mismo tiempo que MethodB1/2.
Espero que esto ayude,
Respondido el 03 de diciembre de 13 a las 15:12
0
Usted dijo
Según tengo entendido, pensaría que 'thisLock' solo evita que otros subprocesos ingresen a esa área específica del código.
Si obtener un bloqueo en 'esto' detendría todas las operaciones en el objeto, es decir, las llamadas a otros métodos por parte de otros subprocesos.
Ya sea que uses lock(this)
or lock(thisLock)
en ambas declaraciones, solo evitará que otros subprocesos ingresen a esa área específica del código.
Pero como práctica general siempre se aconseja no utilizar lock(this)
más bien cree otro objeto y coloque un lock
en ese objeto.
EDITAR si como Sriram Sakthivel
ha comentado, tiene toda la razón, por favor lea ¿Por qué el bloqueo (esto) {...} es malo? para más información por qué debemos evitar lock(this)
contestado el 23 de mayo de 17 a las 12:05
El consejo de no usar lock(this)
hay que ponerlo en perspectiva. Las Directrices de diseño del marco aconsejan en contra de esto, porque es malo desde la perspectiva del marco. Un consumidor de su marco siempre puede bloquear una instancia de un tipo en su marco, lo que podría conducir accidentalmente a un punto muerto. Al escribir una aplicación LOB, existe un control total sobre qué código se escribe y esto podría no ser un problema tan grande. Yo diria que en ese caso lock(this)
está bien, pero usar un bloqueo en una instancia de otro tipo es en realidad una mala práctica. - Steven
Se corrigió el enlace incorrecto, vinculó el enlace de la pregunta actual :) - Sriram Sakthivel
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c# multithreading object locks or haz tu propia pregunta.
¿Afecta la regulación de la este ayuda? - Sriram Sakthivel
La sugerencia de Sriram es la respuesta -- para ser claros,
lock(this)
no es de ninguna manera diferente alock(somethingElse)
cuando se ve aisladamente. - Jon