2009-11-19 16 views
5

Quiero hacer varias instancias de esta clase.C# ¿Pueden las clases múltiples BLOQUEAR el mismo objeto utilizando múltiples referencias?

public class Worker 
{ 
    private object _lockObject; 
    private Thread _workerThread; 
    private string _name; 

    public Worker(object lockObject, string name) 
    { 
     _name = name; 
     _lockObject = lockObject; 
     _workerThread = new Thread(new ThreadStart(DoWork)); 
     _workerThread.Start(); 
    } 
    private void DoWork() 
    { 
     while(true) 
     { 
      lock(_lockObject) 
      { 
       Console.WriteLine(_name + "Doing Work"); 
      } 
     } 
    } 
} 

Si paso el mismo objeto de bloqueo para múltiples instancias de la clase, será un bloqueo en una instancia de clase resultar en la otra instancia de clase de espera en que el bloqueo de ser libre?

static void Main() 
{ 
    private readonly object sharedLockObject = new object(); 
    Worker a = new Worker(sharedLockObject,"a"); 
    Worker b = new Worker(sharedLockObject,"b"); 
    Console.ReadLine(); 
} 

Creo que en el caso anterior, los trabajadores nunca habrá: Console.WriteLine (_name + "que hace el trabajo"); al mismo tiempo?

Solo me gustaría obtener alguna confirmación, ya que no estoy seguro de si el bloqueo() bloqueará la referencia o el objeto al que se hace referencia.

Gracias!

Respuesta

14

Sí, object es un tipo de referencia por lo que está pasando una referencia al mismo objeto, por lo que ese mismo objeto sería utilizado por cada Trabajador. El objeto se usa para bloquear, no la referencia.

+0

gracias "El objeto se utiliza para bloquear, no la referencia" Me encantaría encontrarlo en la especificación de C# – divinci

+1

"La instrucción de bloqueo obtiene el bloqueo de exclusión mutua para un objeto determinado" - http://msdn.microsoft. com/en-us/library/aa664735 (VS.71) .aspx – GraemeF

+1

'El objeto se usa para bloquear, no la referencia. ¿Qué significa? – Alexandre

4

La declaración lock marcará la instancia del objeto, no la variable de referencia.

lock(x) { 
    ... 
} 

es precisamente equivalente a:

System.Threading.Monitor.Enter(x); 
try { 
    ... 
} 
finally { 
    System.Threading.Monitor.Exit(x); 
} 

donde x es una instancia de objeto de un tipo de referencia.

Así que sí :-)

2

le recomiendo que no pasar un objeto compartido que se utiliza para bloquear o usted podría conseguir en algunos puntos muertos desagradables. Use un miembro privado de la clase estática para bloquear en:

public class Worker 
{ 
    private static object _syncRoot = new object(); 
    private Thread _workerThread; 
    private string _name; 

    public Worker(string name) 
    { 
     _name = name; 
     _workerThread = new Thread(new ThreadStart(DoWork)); 
     _workerThread.Start(); 
    } 
    private void DoWork() 
    { 
     while(true) 
     { 
      lock(_syncRoot) 
      { 
       Console.WriteLine(_name + "Doing Work"); 
      } 
     } 
    } 
} 
+2

A menos que también necesite sincronizar el acceso a la misma memoria compartida desde otras ubicaciones en el código además de las múltiples instancias de la clase tghis ... –

+0

Estoy parcialmente de acuerdo con usted, en que si se trata de una sección crítica, podría ser crítico sobre todo instancias. Pero, de nuevo, puede que no, y solo se aplique a esta instancia de objeto, lo que haría su implementación perfectamente correcta. –

+0

@Charles Bretana: si se necesita sincronizar el acceso a la misma memoria compartida desde varias ubicaciones en el código, sería un mejor diseño envolver una clase alrededor de esa memoria compartida y proporcionar acceso sincronizado a ella a través de la interfaz pública de la clase. Estoy de acuerdo con Darin, aquí.Pasar un objeto de sincronización como este se volverá problemático a medida que la base de códigos se hace más grande. –

2

lo que está haciendo el trabajo voluntad, pero por qué no hacer que el _lockObject miembro de la clase staticWorker? Conseguirá el mismo efecto pero está más orientado a objetos.

public class Worker 
{ 
    private static object _lockObject = new object(); 
    private Thread _workerThread; 
    private string _name; 

    public Worker(string name) 
    { 
     _name = name; 
     _workerThread = new Thread(new ThreadStart(DoWork)); 
     _workerThread.Start(); 
    } 
    private void DoWork() 
    { 
     while(true) 
     { 
      lock(_lockObject) 
      { 
       Console.WriteLine(_name + "Doing Work"); 
      } 
     } 
    } 
} 

EDITAR: ¡Huy! No vi la respuesta de @Darin Dimitrov, que es idéntica a la que he publicado aquí. +1 a ti, Darin.

Cuestiones relacionadas