2013-05-21 14 views
11

Napisałem następujący kod do testowania moje rozumienie std::mutexDlaczego blokowania std :: mutex nie blokuje nić

int main() { 
    mutex m; 
    m.lock(); 
    m.lock(); // expect to block the thread 
} 

A potem dostałam system_error: device or resource busy. Czy drugi blok nie powinien blokować wątku?

+2

Jest tylko jeden wątek, dlaczego warto go zablokować? – stijn

+0

Inne wątki zostaną zablokowane; nie ma gwarancji, że bieżnik posiadający muteks będzie posiadał (i faktycznie ta wersja powoduje błąd.) – dlev

+2

Jeśli to drugie połączenie zablokowało wątek, w jaki sposób wątek zostanie odblokowany? –

Odpowiedz

12

Od std::mutex:

Wątek wywołujący nie musi posiadać mutex przed wywołaniem zablokować lub try_lock.

iz std::mutex::lock:

Jeśli blokada jest wywoływana przez wątek, który już posiada mutex, program może impasu. Ewentualnie, jeśli implementacja może wykryć zakleszczenie, można zaobserwować warunek błędu resource_deadlock_would_occur.

i wyjątki klauzula:

Zgłasza std :: system_error gdy wystąpią błędy, w tym błędów bazowego systemu operacyjnego, który uniemożliwiałby blokadę od spełnienia jego specyfikacji. Muteks nie jest zablokowany w przypadku zgłaszania wyjątku.

Dlatego nie powinno się blokować nici. Na twojej platformie implementacja zdaje się być w stanie wykryć, kiedy wątek jest już właścicielem blokady i zgłasza wyjątek. To nie może się zdarzyć na innych platformach, jak wskazano w opisach.

2

(std::mutex nie zostało wymienione w pytaniu, gdy pisałem tę odpowiedź).

To zależy od typu biblioteki mutex i mutex używasz - nie powiedzieli nam. Niektóre systemy zapewniają "mutację rekursywną", która może być nazywana wiele razy w ten sposób tylko wtedy, gdy dzieje się z tego samego wątku (wtedy musisz mieć odpowiednią liczbę odblokowań, zanim inny wątek może ją zablokować), inne biblioteki uznają to za błąd i może zawodzić z wdziękiem (tak jak twój) lub mieć niezdefiniowane zachowanie.

+0

std mutex nie jest rekurencyjny – NoSenseEtAl

+0

, nawet jeśli był rekurencyjny, nie blokowałby. Muteks rekurencyjny blokuje się po raz drugi i czeka na 2 odblokowania. Blokuje jednak drugi wątek. –

+1

Biblioteka jest standardową biblioteką C++ 11, a typem mutex jest 'std :: mutex'. To nie jest rekurencyjny muteks; to się nazywa 'std :: recursive_mutex'. A zachowanie tutaj nie jest rekurencyjne; Daje błąd podczas próby uzyskania drugiego zamka. –

8

Czy drugi m.lock() nie ma zablokować wątku?

Nie, daje niezdefiniowane zachowanie. Drugi m.lock() przerwy przedmiotowego wymogu:

C++ 11 30.4.1.2/7 Wymaga: Jeżeli m jest typu std::mutex lub std::timed_mutex, wątek wywołujący nie jest właścicielem mutex.

Wygląda na to, że Twoja implementacja jest w stanie wykryć, że wątek wywołujący jest właścicielem muteksu i podaje błąd; inne mogą blokować w nieskończoność lub zawodzić w inny sposób.

Powiązane problemy