Jaka jest różnica między wyłączną blokadą a wspólną blokadą?


119

Według Wikipedii

Blokady współdzielone są czasami nazywane „blokadami odczytu”, a blokady na wyłączność są czasami nazywane „blokadami zapisu”.

Czy możesz wyjaśnić powody kryjące się za terminami „udostępniony” i „wyłączny”?


Czy blokada niewyłączna to inna nazwa wspólnej blokady?
Ramesh Papaganti

Odpowiedzi:


419

Zapisałem tę odpowiedź, ponieważ pomyślałem, że będzie to zabawna (i pasująca) analogia:

Pomyśl o zamykanym obiekcie jak o tablicy (zamykanej na klucz) w klasie, w której znajduje się nauczyciel (pisarz) i wielu uczniów (czytelników).

Podczas gdy nauczyciel coś pisze (wyłączna blokada) na tablicy:

  1. Nikt nie może tego przeczytać, ponieważ wciąż jest zapisywany, a ona blokuje twój widok => Jeśli obiekt jest zablokowany na wyłączność, nie można uzyskać wspólnych blokad .

  2. Inni nauczyciele też nie pojawią się i nie zaczną pisać, albo tablica stanie się nieczytelna i dezorientuje uczniów => Jeśli obiekt jest zamknięty na wyłączność, nie można uzyskać innych wyłącznych blokad .

Kiedy uczniowie czytają (wspólne zamki), co jest na tablicy:

  1. Wszyscy mogą przeczytać, co na nim jest, razem => Wiele współdzielonych blokad może współistnieć .

  2. Nauczyciel czeka, aż skończą czytać, zanim wyczyści tablicę, aby napisać więcej => Jeśli jeden lub więcej wspólnych blokad już istnieje, nie można uzyskać wyłącznych blokad .


2
bardzo dobre wyjaśnienie. Platforma zapytała jednak o pochodzenie „wspólnych” i „wyłącznych” nominałów, a nie o wyjaśnienie terminów jako takich.
serhio

Czy to „Jeśli jeden lub więcej współdzielonych blokad już istnieje, nie można uzyskać blokad na wyłączność”. jest prawdziwy? pośrednie z ReentrantReadWriteLock? Myślałem, że blokadę zapisu można uzyskać w dowolnym momencie, w przeciwnym razie może wystąpić głód zapisu z powodu ciągłego czytania.
Kanagavelu Sugumar

1
@KanagaveluSugumar, tak, to prawda. Po prostu nie można uzyskać blokady zapisu, gdy inna jednostka już posiada blokadę odczytu tego samego obiektu. O to właśnie chodzi w przypadku blokady odczytu i zapisu. Jeśli zdarzy ci się nadpisać coś, gdy ktoś inny to czyta, co by wtedy przeczytali? Nie wiem, dlaczego wybrałeś konkretną blokadę „ponownego wejścia” do odczytu i zapisu, ale ponowne wejście oznacza, że ​​właściciel blokady ponownego wejścia może go ponownie zablokować () i wszystkie kolejne lock()wywołania po pierwszy powróci natychmiast i pomyślnie. tzn. możesz z powodzeniem zablokować coś, co już posiadasz.
ArjunShankar

2
Wspomniałeś również, że „Myślałem, że blokadę zapisu można uzyskać w dowolnym momencie, w przeciwnym razie może dojść do głodu zapisu z powodu ciągłego czytania” - to po prostu nie może być. Nie można uzyskać blokady zapisu, podczas gdy inna jednostka już posiada blokadę odczytu / zapisu. Co może się zdarzyć, że w przypadku wielu podmiotów są już czeka, aby zablokować obiekt, a następnie czekanie writerjest pierwszeństwo nad czytelników oczekujących gdy Wybiera lock, który dostaje blokadę obok (gdy jest odblokowany przez jej obecnego właściciela). Tu chodzi o politykę .
ArjunShankar

Dziękuję Ci! Wybrałem ReentrantReadWriteLock; ponieważ jest to klasa implementacji ReadWriteLock w java. Czy jest jakaś flaga podniesiona lub ustawiony wyższy priorytet, aby powiedzieć, że kolejne nowe wątki odczytu mają czekać, gdy rozpocznie się wątek zapisu? Bo jak uniknąć głodu wątku zapisu z powodu ciągłego żądania odczytu?
Kanagavelu Sugumar

34

To całkiem proste. Blokady odczytu są również znane jako blokady współdzielone, ponieważ więcej niż jeden proces może czytać w tym samym czasie. Celem blokady odczytu jest zapobieganie przejęciu blokady zapisu przez inny proces. W przeciwieństwie do tego blokada zapisu blokuje wszystkie inne operacje, gdy operacja zapisu kończy się, dlatego jest opisywana jako wyłączna.

Tak więc blokada odczytu mówi „możesz teraz czytać, ale jeśli chcesz pisać, będziesz musiał czekać”, podczas gdy blokada zapisu mówi „będziesz musiał czekać”.


Zdaję sobie sprawę, że poszukujesz informacji na poparcie swoich studiów, ale nie mogę oprzeć się pokusie wykładu.

Nieumiejętne stosowanie blokowania jest główną przyczyną problemów z wydajnością. Użycie systemu blokowania, który rozróżnia blokady odczytu i zapisu, jest dobrym początkiem, ale staranny projekt może czasami wyeliminować wiele konieczności blokowania. Na przykład stan sesji nigdy nie powinien być przechowywany w jednej kolekcji globalnej na element stanu.

Rzeczywiście widziałem to zrobione. To okropny projekt, powodujący boksowanie i zmianę kolekcji przy każdej ostatniej zmianie stanu sesji, pociągający za sobą przedłużającą się blokadę zapisu. Narzuty były paraliżujące, skutecznie redukując serwer do zachowania jednowątkowego.

Po prostu agregowanie całego stanu sesji w strukturę było ogromnym ulepszeniem. Zmiany stanu sesji spowodowały jedynie zmianę wartości elementów członkowskich struktury stanu sesji. Ponieważ żadna inna sesja nie miała okazji ani nawet możliwości bezpośredniego odniesienia się do stanu sesji, jedyną aktualizowaną kolekcją była lista sesji. W rezultacie blokowanie było całkowicie niepotrzebne podczas sesji, tylko na początku i na końcu, a przepustowość wzrosła 3000 razy.

Innym typowym scenariuszem blokowania są zasoby współdzielone między wątkami aplikacji użytkownika. Większość nowoczesnych frameworków rozwiązuje ten problem za pomocą komunikatów, a nie blokad; kiedy „przechodzisz do wątku interfejsu użytkownika”, w rzeczywistości umieszczasz w kolejce komunikat zawierający wskaźnik funkcji i niektóre parametry (lub delegata i ramkę stosu, w zależności od implementacji).


6
  • Wyłączność lub blokada zapisu daje procesowi wyłączny dostęp do zapisu w określonej części pliku. Kiedy obowiązuje blokada zapisu, żaden inny proces nie może zablokować tej części pliku.

  • Blokada współużytkowana lub blokada odczytu uniemożliwia żadnemu innemu procesowi zażądanie blokady zapisu w określonej części pliku. Jednak inne procesy mogą żądać blokad odczytu.

Więcej na ten temat: http://www.gnu.org/software/libc/manual/html_node/File-Locks.html


2

Zasada jest taka sama po stronie bazy danych. Zgodnie z dokumentacją Oracle

Wyłączny tryb blokady zapobiega współużytkowaniu skojarzonego zasobu. Ten tryb blokady jest uzyskiwany w celu modyfikacji danych. Pierwsza transakcja polegająca na zablokowaniu zasobu na wyłączność jest jedyną transakcją, która może zmienić zasób do czasu zwolnienia blokady na wyłączność.

Tryb blokady udziału umożliwia udostępnianie skojarzonego zasobu w zależności od operacji. Wielu użytkowników odczytujących dane może udostępniać dane, trzymając blokady udziału, aby zapobiec jednoczesnemu dostępowi piszącego (który potrzebuje wyłącznej blokady). Kilka transakcji może
uzyskać wspólne blokady dla tego samego zasobu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.