wielowejściowy blokowania
Blokada wklęsłego jest taki, w którym proces może ubiegać się zablokować kilka razy, bez blokowania na siebie. Jest to przydatne w sytuacjach, gdy nie jest łatwo sprawdzić, czy już złapałeś blokadę. Jeśli zamek nie jest ponownie uczestnikiem, możesz chwycić blokadę, a następnie zablokować, gdy przejdziesz, aby go ponownie chwycić, skutecznie blokując własny proces.
Reentrancy w ogólności jest właściwością kodu, w której nie ma centralnego, zmiennego stanu, który mógłby zostać uszkodzony, gdyby kod został wywołany podczas wykonywania. Takie wywołanie może być wykonane przez inny wątek, lub może być rekurencyjnie wykonane przez ścieżkę wykonawczą pochodzącą z samego kodu.
Jeśli kod jest zależny od stanu współdzielonego, który można zaktualizować w trakcie jego wykonywania, nie jest on ponownie wprowadzany, a przynajmniej nie, jeśli ta aktualizacja może go rozbić.
Przypadek użycia do ponownego uczestnika blokującego
A (nieco rodzajowy i contrived) przykład wniosku o re-uczestnik blokady może być:
Masz jakieś obliczenia udziałem algorytm przechodzący przez wykres (być może z cyklami w nim). Przejście może odwiedzać ten sam węzeł więcej niż jeden raz z powodu cykli lub z powodu wielu ścieżek do tego samego węzła.
Struktura danych podlega współbieżnemu dostępowi i może być aktualizowana z jakiegoś powodu, być może przez inny wątek. Musisz mieć możliwość blokowania poszczególnych węzłów, aby poradzić sobie z potencjalnymi uszkodzeniami danych z powodu warunków wyścigu. Z jakiegoś powodu (może wydajności) nie chcesz globalnie blokować całej struktury danych.
Obliczenia nie mogą zawierać pełnych informacji na temat odwiedzonych węzłów ani struktury danych, która nie pozwala na szybkie odpowiedzi na pytania "już tu byłem".
Przykładem takiej sytuacji byłaby prosta implementacja algorytmu Dijkstry z kolejką priorytetową zaimplementowaną jako stuła binarna lub wyszukiwanie w pełnym zakresie przy użyciu prostej listy połączonej jako kolejki. W takich przypadkach skanowanie kolejki dla istniejących wstawień to O (N) i możesz nie chcieć tego robić w każdej iteracji.
W tej sytuacji śledzenie zamków już zakupionych jest drogie. Zakładając, że chcesz zablokować na poziomie węzła, mechanizm blokady ponownego wejścia zmniejsza potrzebę poinformowania, czy wcześniej odwiedziłeś węzeł. Możesz po prostu ślepo zablokować węzeł, być może odblokować go po wyjęciu go z kolejki.
wielowejściowy muteksy
prosty Muteks nie wklęsła, jak tylko jednej nici można w krytycznym punkcie w danym momencie jest. Jeśli złapiesz muteks, a następnie spróbujesz go ponownie chwycić, prosty muteks nie ma wystarczających informacji, aby powiedzieć, kto go wcześniej trzymał. Aby to zrobić rekurencyjnie, potrzebujesz mechanizmu, w którym każda nić ma token, abyś mógł powiedzieć, kto złapał muteks. To sprawia, że mechanizm mutex jest nieco droższy, więc możesz nie chcieć tego robić we wszystkich sytuacjach.
IIRC API wątków POSIX oferuje opcję muteksów, które mogą być wprowadzane ponownie i niezaangażowane.
Mimo to zazwyczaj należy unikać takich sytuacji, ponieważ utrudnia to również uniknięcie impasu itp. Gwintowanie jest wystarczająco trudne, bez wątpienia, czy masz już zamek. –
+1, weź pod uwagę także przypadek, w którym zamek NIE jest ponownie widoczny, możesz zablokować się na sobie, jeśli nie jesteś ostrożny. Plus w C, nie masz tych samych mechanizmów, co inne języki, aby zapewnić, że blokada jest wydana tyle razy, ile jest ona nabyta. Może to prowadzić do dużych problemów. – user7116
To jest dokładnie to, co przydarzyło mi się wczoraj: nie brałem pod uwagę kwestii ponownego entrancy i zakończyłem debugowanie impasu przez 5 godzin ... – vehomzzz