Mam aplikację wielowątkową, która musi często czytać niektóre dane, a czasami te dane są aktualizowane. W tej chwili mutex zapewnia bezpieczny dostęp do tych danych, ale jest drogi, ponieważ chciałbym, aby wiele wątków mogło czytać jednocześnie i blokować je tylko wtedy, gdy potrzebna jest aktualizacja (wątek aktualizacji może czekać na zakończenie innych wątków) .
Myślę, że to właśnie boost::shared_mutex
powinno zrobić, ale nie jestem pewien, jak go używać, i nie znalazłem jasnego przykładu.
Czy ktoś ma prosty przykład, którego mógłbym użyć, aby rozpocząć?
c++
multithreading
boost
mutex
boost-thread
kevin42
źródło
źródło
Odpowiedzi:
Wygląda na to, że zrobiłbyś coś takiego:
źródło
1800 INFORMACJE jest mniej więcej poprawne, ale jest kilka problemów, które chciałem poprawić.
Zauważ również, że w przeciwieństwie do shared_lock, tylko jeden wątek może uzyskać upgrade_lock w jednym czasie, nawet jeśli nie jest zaktualizowany (co uważałem za niezręczne, kiedy na to wpadłem). Tak więc, jeśli wszyscy twoi czytelnicy są pisarzami warunkowymi, musisz znaleźć inne rozwiązanie.
źródło
boost::unique_lock< boost::shared_mutex > lock(lock);
brzmiećboost::unique_lock< boost::shared_mutex > lock(
_access);
?Od C ++ 17 (VS2015) możesz używać standardu blokad do odczytu i zapisu:
W przypadku starszej wersji możesz użyć funkcji boost z tą samą składnią:
źródło
typedef boost::unique_lock< Lock > WriteLock; typedef boost::shared_lock< Lock > ReadLock;
.Aby dodać więcej informacji empirycznych, badałem cały problem blokad z możliwością aktualizacji i przykład dla zwiększenia shared_mutex (wiele odczytów / jeden zapis)? jest dobrą odpowiedzią, dodając ważne informacje, że tylko jeden wątek może mieć upgrade_lock, nawet jeśli nie jest zaktualizowany, co jest ważne, ponieważ oznacza to, że nie można zaktualizować wspólnej blokady do unikalnej blokady bez uprzedniego zwolnienia wspólnej blokady. (Zostało to omówione w innym miejscu, ale najciekawszy wątek jest tutaj http://thread.gmane.org/gmane.comp.lib.boost.devel/214394 )
Jednak znalazłem ważną (nieudokumentowaną) różnicę między wątkiem oczekującym na aktualizację do blokady (tj. Musi czekać, aż wszyscy czytelnicy zwolnią współdzieloną blokadę) a blokadą pisarza czekającą na to samo (tj. Unique_lock).
Wątek, który czeka na unique_lock na shared_mutex, blokuje przychodzących nowych czytelników, muszą oni czekać na żądanie pisarzy. Gwarantuje to, że czytelnicy nie głodują pisarzy (jednak uważam, że pisarze mogą głodować czytelników).
Wątek, który czeka na aktualizację upgradeable_lock, pozwala innym wątkom uzyskać współdzieloną blokadę, więc ten wątek może zostać zagłodzony, jeśli czytelnicy będą bardzo często.
Jest to ważna kwestia do rozważenia i prawdopodobnie powinna zostać udokumentowana.
źródło
Terekhov algorithm
gwarantuje, że w1.
, pisarz nie może głodować czytelników. Zobacz to . Ale2.
to prawda. Upgrade_lock nie gwarantuje uczciwości. Zobacz to .Użyj semafora z liczbą równą liczbie czytelników. Niech każdy czytelnik policzy semafor po jednym policzeniu, aby móc czytać, tak aby wszyscy mogli czytać w tym samym czasie. Następnie pozwól pisarzowi wziąć WSZYSTKIE liczby semaforów przed napisaniem. Powoduje to, że piszący czeka na zakończenie wszystkich odczytów, a następnie blokuje odczyty podczas pisania.
źródło
Świetna odpowiedź Jima Morrisa. Natknąłem się na to i zajęło mi trochę czasu, zanim zrozumiałem. Oto prosty kod, który pokazuje, że po przesłaniu „żądania” wzmocnienia unique_lock (wersja 1.54) wszystkie żądania shared_lock zostaną zablokowane. Jest to bardzo interesujące, ponieważ wydaje mi się, że wybór między unique_lock i upgradeable_lock pozwala na to, czy chcemy pisać priorytet, czy nie.
Również (1) w poście Jima Morrisa wydaje się temu zaprzeczać: Boost shared_lock. Czytaj preferowane?
źródło