2013-01-17 9 views
7

Ho la seguente situazione: Voglio escludere reciprocamente l'accesso a un oggetto.È possibile bloccare e monitorare lo stesso oggetto in modo sicuro?

Finora ho normalmente sarebbe utilizzare un oggetto di blocco

object lockObject = new object(); 
... 

method1: lock(lockObject) { CODE1 } 

Ora ho anche un metodo che può essere chiamato da un altro thread. Non dovrebbe essere bloccato per un tempo sconosciuto, invece dovrebbe dare una risposta in un tempo definito.

In questo caso vorrei usare un monitor, come

method2: 
try{ 
    Monitor.TryEnter(lockObject , 20000, ref lockTaken); 
    if (lockTaken) {CODE2} 
} 
catch(...){...} 
finally 
{ 
    if (lockTaken) Monitor.Exit(timerLock); 
} 

Ora la mia domanda è: può bloccare e monitorare essere mescolati in modo tale se il LockObject è lo stesso ed escludere a vicenda, o se è necessario cambiare ogni blocco su un monitor.

Quindi entrambe le volte lo stesso token deve essere "bloccato" oppure il monitor crea un altro token per l'oggetto e quindi il lucchetto?

In un colpo d'occhio non riesco a vedere che l'applicazione venga eseguita in codice di entrambi allo stesso tempo. Ma non so se possono esistere problemi di temporizzazione, dove CODE1 e CODE2 sono eseguiti in parallelo.

+1

sento il tuo dolore; Spesso mi auguro che la parola chiave 'lock' abbia preso un timeout in qualche modo –

risposta

6
lock (sync) 
{ 
    return World(); 
} 

Guarderebbe le linee di questo in Intermediate Language.

L_0007: call void [mscorlib]System.Threading.Monitor::Enter(object) 
L_000c: call int32 Hello::World() 
L_0011: stloc.0 
L_0012: leave.s L_001b 
L_0014: ldloc.1 
L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object) 

Quindi dovrebbe andare bene. Sono tecnicamente equivalenti.

+0

nota che le versioni recenti di csc, quando si effettua il targeting su .NET 4 o versioni successive, avranno un IL diverso da questo –

+0

Grazie, vero. L'ho fatto solo per l'illustrazione approssimativa. –

5

può bloccare e monitorare essere mescolati in tal modo se il LockObject è lo stesso e reciprocamente escludono reciprocamente

Sì, che è totalmente sicuro e funzionerà.

L'istruzione lock { } viene riscritta per le chiamate a Monitor.Enter() e Monitor.Exit(). È solo una mano breve, molto simile alla dichiarazione .

Da MSDN:

lock (x) ... 

diventa

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

E come per il commento, in FX4 e poi si può usare Monitor.TryEnter(). Ma la semplice versione sopra risponde alla tua domanda.

+2

o Monitor.TryEnter quando il targeting .NET 4+. –

Problemi correlati