2010-11-02 27 views
5

soy muy nuevo en C# y quería preguntarle si tengo esta situación en MULTI HILOS (pseudo código):bloqueo en una variable en múltiples hilos

public class ClassA 
{ 
    ClassB c = new ClassB(); 
    public void someMethod() 
    { 
      c.myVar = 1; 
      // Some other stuff 
      c.myVar = 0; 
    } 
} 

public class ClassB 
{ 
    private int myVar; 

    public void MethodA() 
    { 
     if(myVar = 1) 
       myVar = 0; 
    } 
} 

Si algunMetodo() y MethodA() puede estar activo en hilos separados, entonces MethodA() podría evaluar el enunciado if como verdadero; pero antes de establecer myVar = 0 someMethod establece myVar = 0 por lo que es incorrecto haber establecido myVar en 0 en MethodA() !!

Básicamente, ¿cómo bloqueo myVar: puedo bloquear {} en la propiedad de myVar (establecer, obtener) o necesito usar Interlock (aún no tengo experiencia de Interlock)?

+2

1) No llame a una variable del tipo ClassB para c, eso es confuso. –

+1

¿quisiste decir 'if (myVar == 1)'? – Vlad

+2

2) No puede acceder a c.myVar ya que es un miembro privado de ClassB. –

Respuesta

1

Así es como lo hago.

static readonly object _myVar_Lock = new object(); 
    private int _myVar = 0; 

    public int myVar 
    { 
     get { lock (_myVar_Lock) { return this._myVar; } } 
     set { lock (_myVar_Lock) { this._myVar = value; } } 
    } 
+1

No, esto es completamente inútil, la lectura y escritura de esto._miVar en este caso es atómica de acuerdo con la especificación C#. (ya que es un int). El bloqueo es necesario para manejar el caso 'if (myVar == 1) myVar = 0;' sin la posibilidad de que otro hilo cambie myVar a permite decir 2 en el medio. –

+0

Albin - por favor, ¿puedes explicar un poco más por qué esto no funcionará? – SimpleOne

+0

Albin, estás equivocado. ¿Por qué habría un método Exchange() en la clase Interbloqueado si "miVar = valor" es atómico? La respuesta es que la escritura no es atómica. http://msdn.microsoft.com/en-us/library/d3fxt78a.aspx –

-1

¿Hay alguna razón para que haya múltiples hilos que comparten la misma instancia de la clase en lugar de implementar cada hilo de modo que consiga su propia instancia de la clase dentro de su alcance?

3

Parece que está intentando implementar algún tipo de mecanismo de señalización. En lugar de escribir el suyo, puede usar una de las clases proporcionadas en la biblioteca .NET como ManualResetEvent.

15

Debe crear un objeto privado que permitirá el bloqueo:

private readonly object _locker = new object(); 

Luego, en su propiedad métodos get/set, bloqueo alrededor de él:

get { lock (_locker) { return this.myVar; } } 
set { lock (_locker) { this.myVar = value; } } 

Asegúrese de que su método utiliza la cerradura también:

public void MethodA() 
{ 
    lock(_locker) 
    { 
     if(myVar == 1) 
      myVar = 0; 
    } 
} 
+0

¿Necesito un candado similar para el juego {}? – SimpleOne

+0

Sí, si necesita un colocador. Actualizaré – aqwert

+0

¿Cómo aborda esto la condición de carrera en 'someMethod'? –

1

Sin duda volvería a pensar en su enfoque general, pero si desea Para sincronizar el acceso a los miembros de ClassB desde diferentes secciones de código, entonces podría robar un patrón de diseño no tan bueno de la interfaz ICollection y exponer una propiedad SyncRoot que se puede usar para adquirir el mismo bloqueo que la instancia original.

public class ClassA 
{ 
    private ClassB c = new ClassB(); 

    public void someMethod() 
    { 
    lock (c.SyncRoot) 
    { 
     c.MyVar = 1; 
     // Some other stuff 
     c.MyVar = 0; 
    } 
    } 
} 

public class ClassB 
{ 
    private object m_LockObject = new object(); 
    private int m_MyVar; 

    public object SyncRoot 
    { 
    get { return m_LockObject; } 
    } 

    public int MyVar 
    { 
    get { lock (SyncRoot) return m_MyVar; } 
    set { lock (SyncRoot) m_MyVar = value; } 
    } 

    public void MethodA() 
    { 
    lock (SyncRoot) 
    { 
     if (m_MyVar == 1) m_Var = 0; 
    } 
    } 
} 
Cuestiones relacionadas