2013-01-17 18 views
7

Mam następujące sytuacji: chcę wzajemnie wykluczać dostęp do obiektu.Czy można bezpiecznie blokować i monitorować ten sam obiekt?

tej pory normalnie byłoby użyć obiektu blokady

object lockObject = new object(); 
... 

method1: lock(lockObject) { CODE1 } 

Teraz mam również metodę, która może być wywołana z innego wątku. Nie powinien być blokowany na nieznany czas, zamiast tego powinien udzielić odpowiedzi w określonym czasie.

W tym przypadku chciałbym użyć monitora, jak

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

teraz moje pytanie brzmi: może zablokować i monitor być mieszane w taki sposób, jeśli lockobject jest taka sama i wzajemnie wykluczają się wzajemnie, czy będzie trzeba zmienić każdy zamek na monitor.

Czy oba razy ten sam żeton będzie "zablokowany", czy monitor utworzy kolejny token dla obiektu, a następnie blokadę?

W mgnieniu oka nie widzę, że aplikacja działa jednocześnie w kodzie. Ale nie wiem, czy mogą wystąpić problemy z timingiem, gdzie CODE1 i CODE2 są wykonywane równolegle.

+1

Czuję twój ból; Często żałuję, że słowo kluczowe "lock" nie upłynęło w jakiś sposób –

Odpowiedz

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

Spójrz na to w języku średnio zaawansowanym.

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) 

Powinno być dobrze. Są one technicznie równoważne.

+0

Należy pamiętać, że ostatnie wersje csc, przy kierowaniu na .NET 4 lub nowszy, będą miały inną wartość IL niż ta –

+0

Dzięki, prawda. Po prostu zrobiłem to z grubsza. –

5

może zablokować i monitorować mieszać w taki sposób, jeśli lockobject jest taka sama i wzajemnie wykluczają się wzajemnie

Tak, że jest całkowicie bezpieczny i będzie działać.

Instrukcja lock { } została przepisana na wywołania funkcji Monitor.Enter() i Monitor.Exit(). Jest po prostu krótki, bardzo podobny do stwierdzenia using() {}.

Od MSDN:

lock (x) ... 

staje

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

I jak na komentarz, w fx4 a później można go użyć Monitor.TryEnter(). Ale prosta wersja powyżej odpowiada na twoje pytanie.

+2

lub Monitor.TryEnter przy kierowaniu na .NET 4+. –

Powiązane problemy