2009-08-21 16 views
68

Zawsze się mylę. Czy ktoś wytłumaczyłby, co znaczy Reentrant w różnych kontekstach? I dlaczego chciałbyś użyć reentrant kontra non-reentrant?Co to jest blokada i koncepcja Re-Entrant w ogóle?

Powiedz primeitów blokujących pthread (posix), czy są one ponownie wprowadzane czy nie? Jakich pułapek należy unikać podczas ich używania?

Czy uczestnik muteksu jest ponownie uczestnikiem?

Odpowiedz

125

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.

+1

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. –

+0

+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

+1

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

17

Re-uczestnik blokady pozwala napisać metodę M które stawia blokadę na zasób A a następnie zadzwonić M rekurencyjnie lub z kodem, który już posiada blokadę na A.

Przy zamknięciu bez ponownego łączenia potrzebne są 2 wersje M, jedna blokująca, a druga nie, i dodatkowa logika do połączenia z właściwą.

+1

Tutaj może być pomocne wyjaśnienie rysunkowe ... – Rachel

9

Blokada Reentrant jest bardzo dobrze opisana w tym tutorial.

Przykład w samouczku jest znacznie mniej wymyślny niż w odpowiedzi na temat przechodzenia przez wykres. Blokada ponownego dostępu jest przydatna w bardzo prostych przypadkach.