2013-06-24 11 views
7

Mi chiedevo: Locking consente solo 1 thread per entrare in una regione di codiceAutoResetEvent come sostituzione di un blocco in C#?

E aspettare maniglie è per la segnalazione::

segnalazione è quando uno thread attende finché non riceve notifica da un'altra.

Quindi ho pensato a me stesso, può essere utilizzato per sostituire una serratura?

qualcosa di simile:

Thread number 1 --please enter (autoreset --> autlock) 
dowork... 
finish work... 
set signal to invite the next thread 

Così ho scritto questo:

/*1*/ static EventWaitHandle _waitHandle = new AutoResetEvent(true); 
/*2*/ 
/*3*/ volatile int i = 0; 
/*4*/ void Main() 
/*5*/ { 
/*6*/ 
/*7*/  for (int k = 0; k < 10; k++) 
/*8*/  { 
/*9*/   var g = i; 
/*10*/   Interlocked.Increment(ref i); 
/*11*/   new Thread(() = > DoWork(g)).Start(); 
/*12*/ 
/*13*/  } 
/*14*/ 
/*15*/  Console.ReadLine(); 
/*16*/ } 
/*17*/ 
/*18*/ 
/*19*/ void DoWork(object o) 
/*20*/ { 
/*21*/  _waitHandle.WaitOne(); 
/*22*/  Thread.Sleep(10); 
/*23*/  Console.WriteLine((int) o + "Working..."); 
/*24*/  _waitHandle.Set(); 
/*25*/ 
/*26*/ } 

come si può vedere: le linee 21 #, # 24 è la sostituzione per il blocco.

Domanda:

  • E 'un valido sostituto? (non che sostituirò lock, ma voglio sapere degli scenari di utilizzo)
  • Quando dovrei usarli?

Grazie.

strano ma così non contiene una domanda per quanto riguarda _lock vs EventWaitHandle_

+0

SO ha una domanda simile: http://stackoverflow.com/questions/1717194/autoresetevent-manualresetevent-vs-monitor – empi

+0

@empi heh, tutti i 3 termini sono nella composizione generale (monitor.enter vs lock, autoreset vs waithandle ....) ma sì è simile.tuttavia si noti che 'AutoResetEvent/waithdnales' sono ** non condivisi ** tra processi. lo scrittore ha confuso con Mutex. comunque lui ha torto. (a tale proposito). –

+0

@empi anche la risposta più votata parla delle differenze quando c'è un comando set (meteo se thread è in attesa o no). –

risposta

11

Non andare lì. Una proprietà importante di una serratura è che fornisce equità. In altre parole, una ragionevole garanzia che i thread che si contendono il lock ottengano la garanzia di poterli eventualmente acquisire. La classe Monitor fornisce tale garanzia, implementata da una coda di attesa nel CLR. E Mutex e Semaphore forniscono tale garanzia, implementata dal sistema operativo.

WaitHandles do non fornire tale garanzia. Il che è molto dannoso se il blocco viene conteso, lo stesso thread può acquisirlo ripetutamente e altri thread possono morire di fame per sempre.

Utilizzare un oggetto di sincronizzazione appropriato per i blocchi. Le maniglie di attesa dovrebbero essere utilizzate solo per la segnalazione.

+0

_fairness_ - Ciò significa che se i thread: 1,5,7 (in quest'ordine) sono nella regione di blocco, il blocco (quando rilasciato) sarà equo e verrà rilasciato ai thread 1 -> 5 -> 7? (mentre waitHandles può fare: 1 -> 1 -> 1 - perché il thread potrebbe avere una priorità processo/thread più alta?) –

+0

Ci sono alcuni aspetti peculiari relativi agli APC, quindi questo non è esattamente il caso. Ma sì, questo è il normale ordine in cui i thread acquisiscono un lock quando l'oggetto sync promette l'equità. –

+0

Hans Ho anche letto da qualche parte che: se c'è ** nessun altro thread ** che vuole il lock - la risorsa del kernel (o qualcosa del genere) non è nemmeno presa .... puoi farmi riferimento per favore al termine giusto? –

1

E 'possibile, ma è molto più lento di blocco() e molto più difficile da mantenere.

A proposito, non si dovrebbe mai leggere direttamente un valore quando si usano metodi Interlock per mantenerlo.

Il codice dovrebbe essere simile a questa:

var g = Interlocked.Increment(ref i); 

Poi g conterrà il valore incrementato piuttosto che un valore precedente abitrary.

Problemi correlati