2009-11-19 15 views
5

Voglio rendere più istanze di questa classe.C# È possibile che più classi BLOCCA lo stesso oggetto utilizzando più riferimenti?

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"); 
      } 
     } 
    } 
} 

Se mi passa lo stesso oggetto di blocco a più istanze della classe, sarà un blocco in un'istanza di classe comportare l'altra istanza di classe in attesa di quel blocco di essere liberi?

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

penso che nel caso di cui sopra, i lavoratori saranno mai: Console.WriteLine (_name + "che fa lavoro"); allo stesso tempo?

Vorrei solo una conferma, poiché non sono sicuro se il blocco() bloccherà il riferimento o l'oggetto a cui si fa riferimento.

Grazie!

risposta

14

Sì, object è un tipo di riferimento in modo da passare un riferimento allo stesso oggetto, in modo che lo stesso oggetto venga utilizzato da ciascun lavoratore. L'oggetto è utilizzato per il blocco, non il riferimento.

+0

grazie "L'oggetto è utilizzato per il blocco, non il riferimento" piacerebbe trovarlo nella specifica C# – divinci

+1

"L'istruzione di blocco ottiene il blocco di esclusione reciproca per un dato oggetto" - http://msdn.microsoft. it/it/us/library/aa664735 (VS.71) .aspx – GraemeF

+1

'L'oggetto è utilizzato per il blocco, non il riferimento. Che cosa significa? – Alexandre

4

L'istruzione lock segnerà l'istanza dell'oggetto, non la variabile di riferimento.

lock(x) { 
    ... 
} 

è proprio equivalente a:

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

dove x è un'istanza oggetto di un tipo di riferimento.

Quindi sì :-)

2

ti consiglierei di non passare un oggetto condiviso che si utilizza per il blocco o si potrebbe ottenere in alcune situazioni di stallo brutto. Usare un membro privato statico della classe per bloccare il:

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 meno che non abbia anche bisogno di sincronizzare l'accesso alla stessa memoria condivisa da altre posizioni nel codice oltre alle più istanze di classe tghis ... –

+0

Sono parzialmente d'accordo con te, nel senso che se si tratta di una sezione critica, potrebbe essere fondamentale su tutti le istanze. Ma di nuovo potrebbe non esserlo, e si applicherà solo a questa istanza dell'oggetto, che renderebbe perfettamente soddisfacente la sua implementazione. –

+0

@Charles Bretana: Se è necessario sincronizzare l'accesso alla stessa memoria condivisa da più posizioni nel codice, sarebbe un design migliore per avvolgere una classe attorno a quella memoria condivisa e fornire accesso sincronizzato ad essa attraverso l'interfaccia pubblica della classe. Sono d'accordo con Darin, qui.Passare un oggetto di sincronizzazione in questo modo diventerà problematico con l'aumentare della base di codice. –

2

ciò che si sta facendo un lavoro volontà, ma perché non fare il _lockObject membro della classe di Workerstatic? Otterrà lo stesso effetto ma è più orientato agli oggetti.

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"); 
      } 
     } 
    } 
} 

EDIT: Oops! Non ho visto la risposta di @Darin Dimitrov, che è identica a quella che ho postato qui. +1 a te, Darin.

Problemi correlati