Motywacja: powód, dla którego rozważam to, że mój genialny kierownik projektu uważa, że doładowanie jest kolejną zależnością i że jest okropne, ponieważ "jesteś od niego zależny" (próbowałem wyjaśnić jakość wzmocnienia, ale po pewnym czasie zrezygnowałem :( Mniejszym powodem, dla którego chciałbym to zrobić, jest to, że chciałbym nauczyć się funkcji języka c ++ 11, ponieważ ludzie zaczną pisać w nim kod.
- Czy istnieje mapowanie 1: 1 między odpowiednikami
#include<thread> #include<mutex>
i boost? - Czy rozważyłbyś dobry pomysł, aby zamienić rzeczy boost na rzeczy z c ++ 11
. Moje użycie jest prymitywne, ale czy są przykłady, kiedy std nie oferuje tego, co zapewnia wzmocnienie? Czy (bluźnierstwo) odwrotnie?
PS Używam GCC, więc są tam nagłówki.
Odpowiedzi:
Istnieje kilka różnic między Boost.Thread a standardową biblioteką wątków C ++ 11:
std::async
, ale Boost nieboost::shared_mutex
blokadę dla wielu czytników / jednego zapisującego. Analogicznestd::shared_timed_mutex
jest dostępne tylko od C ++ 14 ( N3891 ), natomiaststd::shared_mutex
jest dostępne tylko od C ++ 17 ( N4508 ).boost::unique_future
vs.std::future
)std::thread
różni się od funkcjiboost::thread
--- Boostboost::bind
, które wymagają kopiowalnych argumentów.std::thread
zezwala na typy tylkostd::unique_ptr
do przenoszenia, takie jak przekazywanie jako argumentów. Ze względu na użycieboost::bind
semantyki symboli zastępczych, takich jak_1
w wyrażeniach zagnieżdżonych powiązań, również może być inna.join()
lubdetach()
wówczasboost::thread
operator destructor i przypisanie wezwiedetach()
na obiekcie wątku niszczone / przypisany. W przypadku obiektu C ++ 11std::thread
spowoduje to wywołaniestd::terminate()
i przerwanie aplikacji.Aby wyjaśnić kwestię parametrów tylko do przenoszenia, poniżej przedstawiono prawidłowy C ++ 11 i przenosi własność
int
z tymczasowegostd::unique_ptr
na parametr, wf1
którym uruchamiany jest nowy wątek. Jeśli jednak użyjeszboost::thread
, nie zadziała, ponieważ używaboost::bind
wewnętrznie istd::unique_ptr
nie można go skopiować. Istnieje również błąd w bibliotece wątków C ++ 11 dostarczonej z GCC, który uniemożliwia to działanie, ponieważ używa jej równieżstd::bind
w implementacji.Jeśli używasz Boost, prawdopodobnie możesz stosunkowo bezboleśnie przełączyć się na wątki C ++ 11, jeśli twój kompilator to obsługuje (np. Najnowsze wersje GCC na Linuksie mają prawie kompletną implementację biblioteki wątków C ++ 11 dostępną w
-std=c++0x
trybie).Jeśli Twój kompilator nie obsługuje wątków C ++ 11, możesz uzyskać implementację innej firmy, taką jak Just :: Thread , ale nadal jest to zależność.
źródło
lock
/unlock
dla pisarzy a „lock_shared / unlock_shared” dla czytelników). Wielu czytelników może wywoływać lock_shared bez blokowania, o ile żaden pisarz nie używa go.shared_mutex
jest dostępna pod adresem boost.org/doc/libs/1_47_0/doc/html/thread/… . Możesz zablokować mutex jako współdzielony lub wyłączny, a następnie użyć odpowiedniej funkcji odblokowania. Możesz również użyć do tego typów RAII (shared_lock
bierze wspólną blokadę odczytulock_guard
iunique_lock
wyłączność). Próbowałem wyjaśnić kwestię typów tylko do ruchu.try_scoped_lock
funkcje są objętestd::unique_lock
. Istnieje konstruktor, który pobiera muteks istd::try_to_lock
, a następnie wywołatry_lock()
muteks zamiastlock()
. Zobacz stdthread.co.uk/doc/headers/mutex/unique_lock/…std::thread
jest w dużej mierze wzorowany naboost::thread
, z kilkoma różnicami :To pochodzi z 2007 roku, więc niektóre punkty są już nieaktualne:
boost::thread
manative_handle
teraz funkcję i, jak podkreślają komentatorzy,std::thread
nie ma już anulowania.Nie mogłem znaleźć żadnych znaczących różnic między
boost::mutex
istd::mutex
.źródło
std::thread
nie ma anulowania; to jestboost::thread
to!interrupt()
boost :: thread? Wygląda również na to, że jest to oryginalna propozycja, która zmieniła się od 2007 roku.Jest jeden powód, dla którego nie warto migrować do
std::thread
.Jeśli używasz linkowania statycznego,
std::thread
staje się bezużyteczny z powodu tych błędów / funkcji gcc:Mianowicie, jeśli zadzwonisz
std::thread::detach
lubstd::thread::join
doprowadzi to do wyjątku lub awarii, podczas gdyboost::thread
działa dobrze w tych przypadkach.źródło
libpthread.a
. Czy jesteś absolutnie pewien tego, co mówisz?Wl,--whole-archive -lpthread -Wl,--no-whole-archive
, zobacz tę odpowiedź, na przykład stackoverflow.com/a/23504509/72178 . Ale nie jest to bardzo prosty sposób łączenia się zlibpthread.a
pomysłem i również uważany za zły.Sprawa Enterprise
Jeśli piszesz oprogramowanie dla przedsiębiorstwa, które musi działać na średniej lub dużej różnorodności systemów operacyjnych, a co za tym idzie, kompilować je z różnymi kompilatorami i wersjami kompilatorów (zwłaszcza stosunkowo starymi) w tych systemach operacyjnych, radzę trzymać się z daleka od C ++ 11 na razie w ogóle. Oznacza to, że nie możesz używać
std::thread
i polecam używanieboost::thread
.Podstawowy / Tech Startup Case
Jeśli piszesz dla jednego lub dwóch systemów operacyjnych, wiesz na pewno, że będziesz musiał budować tylko za pomocą nowoczesnego kompilatora, który w większości obsługuje C ++ 11 (np. VS2015, GCC 5.3, Xcode 7), a jeszcze nie jesteś zależne od biblioteki boost,
std::thread
może to być dobra opcja.Moje doświadczenie
Osobiście jestem zwolennikiem zahartowanych, intensywnie używanych, wysoce kompatybilnych, wysoce spójnych bibliotek, takich jak boost kontra bardzo nowoczesna alternatywa. Jest to szczególnie ważne w przypadku skomplikowanych tematów programowania, takich jak wątki. Ponadto od dawna odniosłem wielki sukces z
boost::thread
(i ogólnie ulepszeniem) w szerokiej gamie środowisk, kompilatorów, modeli wątków itp. Kiedy wybieram, wybieram przyspieszenie.źródło
std::mutex
Wydaje się, że program Visual Studio 2013 zachowuje się inaczej niż programboost::mutex
, co spowodowało pewne problemy (zobacz to pytanie ).źródło
W odniesieniu do std :: shared_mutex dodanego w C ++ 17
Pozostałe odpowiedzi zapewniają bardzo dobry przegląd ogólnych różnic. Jest jednak kilka problemów związanych z
std::shared_mutex
tym wzmocnieniem.Muteksy z możliwością aktualizacji. Tych nie ma
std::thread
. Umożliwiają one zmianę czytelnika na pisarza bez pozwolenia innym pisarzom na wejście przed tobą . Umożliwiają one wykonywanie takich czynności, jak wstępne przetwarzanie dużych obliczeń (na przykład ponowne indeksowanie struktury danych) w trybie odczytu, a następnie aktualizację do zapisu w celu zastosowania ponownego indeksowania, przytrzymując blokadę zapisu tylko przez krótki czas.Uczciwość. Jeśli masz ciągłą aktywność w czytaniu z a
std::shared_mutex
, twoi pisarze będą na czas nieokreślony zablokowani. Dzieje się tak, ponieważ jeśli pojawi się inny czytelnik, zawsze będzie miał pierwszeństwo. W przypadkuboost:shared_mutex
wszystkich wątków ostatecznie nadany zostanie priorytet. (1) Ani czytelnicy, ani pisarze nie będą głodni.Tl; dr polega na tym, że jeśli masz system o bardzo dużej przepustowości, bez przestojów i bardzo dużej rywalizacji,
std::shared_mutex
nigdy nie zadziała bez ręcznego zbudowania systemu priorytetowego.boost::shared_mutex
zadziała po wyjęciu z pudełka, chociaż w niektórych przypadkach może być konieczne majstrowanie przy nim. Twierdzę, żestd::shared_mutex
to zachowanie jest ukrytym błędem, który czeka na wystąpienie w większości kodu, który go używa.(1) rzeczywiste algorytm wykorzystuje opiera się na scheduler wątku OS. Z mojego doświadczenia wynika, że gdy odczyty są nasycone, w systemie Windows występują dłuższe przerwy (przy uzyskiwaniu blokady zapisu) niż w systemie OSX / Linux.
źródło
Próbowałem użyć shared_ptr z std zamiast boost i faktycznie znalazłem błąd w implementacji gcc tej klasy. Moja aplikacja ulegała awarii z powodu dwukrotnego wywołania destruktora (ta klasa powinna być bezpieczna dla wątków i nie powinna generować takich problemów). Po przejściu do boost :: shared_ptr wszystkie problemy zniknęły. Obecne implementacje C ++ 11 wciąż nie są dojrzałe.
Boost ma też więcej funkcji. Na przykład nagłówek w wersji standardowej nie zapewnia serializatora do strumienia (tj. Cout << duration). Boost ma wiele bibliotek, które używają własnych, itp. Odpowiedników, ale nie współpracują z wersjami standardowymi.
Podsumowując - jeśli masz już aplikację napisaną przy użyciu boosta, bezpieczniej jest zachować kod w takiej postaci, w jakiej jest, zamiast wkładać trochę wysiłku w przejście na standard C ++ 11.
źródło
shared_ptr
Destruktor nie musi być bezpieczny wątku, to niezdefiniowane zachowanie mieć jeden wątek z uzyskaniem dostępu do obiektu, podczas gdy inny wątek jest zniszczenie. Jeśli uważasz, że znalazłeś błąd w shared_ptr GCC, zgłoś go , w przeciwnym razie, biorąc pod uwagę prawdopodobieństwo, używasz go nieprawidłowo.