2010-02-23 10 views
8

¿Cuál es la diferencia (si la hay) entre el uso de¿Qué pasar a la palabra clave de bloqueo?

void MethodName() 
{ 
    lock(this) 
    { 
     // (...) 
    } 
} 

o

private object o = new object(); 
void MethodName() 
{ 
    lock(o) 
    { 
     // (...) 
    } 
} 

?

¿Hay alguna diferencia en el rendimiento? ¿Estilo? ¿Comportamiento?

Respuesta

11

La diferencia es que cualquiera puede bloquear su instancia, pero solo usted puede bloquear un objeto privado.

Esto ayuda a prevenir interbloqueos.

Por ejemplo:

Digamos que Microsoft utiliza lock(this) en la clase Control.

Luego, si alguien más se bloquea en una instancia de Control, su bloqueo evitaría que se ejecute el código en Control, que no es lo que él quiere.

Esto es particularmente malo si lock on types that are shared across AppDomains

+0

Niza punto acerca de la debilidad de las cerraduras de identidad. –

17

lock(this) se bloqueará en el objeto "actual".

Bloquear en "esto" suele ser una mala idea, ya que expone el bloqueo a otro código; Yo prefiero tener un campo de sólo lectura, como esto:

public class Foo 
{ 
    private readonly object padlock = new object(); 

    public void SomeMethod() 
    { 
     lock(padlock) 
     { 
      ... 
     } 
    } 
} 

de esa manera todas las llamadas a SomeMethod (y cualquier otra cosa en Foo que bloquea el padlock) se cierran con llave en el mismo monitor de la misma instancia de Foo, pero nada de lo contrario, puede interferir al bloquear ese monitor.

En realidad, a menos que usted está tratando con el código "canalla", es poco probable que otro código se realidad bloqueo en la referencia a una instancia de Foo, pero es una cuestión de encapsulación.

+1

Debo añadir que la verdadera ventaja de esto no es solo evitar que el código deshonesto (o incompetente) te bloquee, sino que también permita el envolvimiento. Puede exponer su objeto de casillero como una propiedad SyncLock o exponer la propiedad SyncLock del objeto que está envolviendo. De esta forma, los bloqueos en la instancia de envoltura se convierten en bloqueos en la instancia envuelta. –

+0

'candado' parece que falta una declaración de tipo. – Dan

+0

@Dan: corregido, gracias. –

1

Hay una diferencia en su alcance y no puede haber una diferencia en el comportamiento (dicho sea de paso, el uso de "esto" no es recomendado por MS

 

// in this case, your lock object is public, so classes outside of this can lock on the same thing 
lock(this) {} 

// in this case, your lock is private, and only you can issue a lock statement against it 
private object lockobj = new object() 
.. 
lock(this.lockobj) {} 

// this one is WRONG -- you willget a new object instance every time, so your lock will not provide mutual exclusion 
void SomeMethod() 
{ 
    // using a local variable for a lock -- wrong 
    object obj = new object(); 
    lock(obj) {} 
} 
 
3

El patrón que suelo seguir es este, para una clase declarada static ....

 
public static class SomeClass{ 
    private static object objLock = new object(); 
    .... 
    public static object SomeProperty{ 
     get{ 
      lock(objLock){ 
      // Do whatever needs to be done 
      } 
     } 
     set{ 
      lock(objLock){ 
      } 
     } 
    } 
} 

Asimismo para una clase normal, me gustaría seguir este patrón:

 
public class SomeClass{ 
    private readonly object objLock = new object(); 
    .... 
    public object SomeProperty{ 
     get{ 
      lock(objLock){ 
      // Do whatever needs to be done 
      } 
     } 
     set{ 
      lock(objLock){ 
      } 
     } 
    } 
} 

De esa manera, nadie puede bloquear en mi instancia y evitará estancamientos de ocurriendo ...

Editar: He modificado este artículo para que sea más clara con respecto al código en la base de la Se usaría static candado y para una clase normal ...Gracias Steven y Dalle por sus salidas de punto ...

+1

¿Estás seguro de que pretendías un bloqueo "estático"? – dalle

+0

@dalle: Sí, lo usaría en una clase estática, haría lo siguiente, 'objeto privado de solo lectura objLock = new object()' dentro de una clase normal. ¿Responde esto a tu pregunta? :) – t0mm13b

+0

No estaba claro en su ejemplo que estuviera en una clase estática. Ahora que ha especificado esto, también tiene sentido que el casillero sea estático. Sus convenciones de nombres hacen que sea más difícil comprender su intención, ya que violan los estándares .NET. –

Cuestiones relacionadas