[C++] std::atomic, a działanie std::memory_order_relaxed
Ostatnio zmodyfikowano 2013-06-05 12:27
fers334 Temat założony przez niniejszego użytkownika |
[C++] std::atomic, a działanie std::memory_order_relaxed » 2013-06-02 10:30:43 Witam mam problem , a mianowicie to że nie wiem dlaczego program nie działa tak jak powinien. Oto program : #include <atomic> #include <thread> #include <assert.h>
std::atomic < bool > x, y; std::atomic < int > z;
void write_x_then_y() { x.store( true, std::memory_order_relaxed ); y.store( true, std::memory_order_relaxed ); } void read_y_then_x() { while( !y.load( std::memory_order_relaxed ) ); if( x.load( std::memory_order_relaxed ) ) ++z; }
int main() { x = false; y = false; z = 0; std::thread a( write_x_then_y ); std::thread b( read_y_then_x ); a.join(); b.join(); assert( z.load() != 0 ); } Problem jest w tym , że podczas ustawienia porządkowania złagodzonego funkcja assert powinna móc wskazać błąd ponieważ operacja ładowania zmiennej x może odczytac false,lecz w moim programie do tego nie dochodzi, zawsze zostaje odczytana wartość true.W książce jest dokładnie ten przykład wiec nie mam pojęcia dlaczego mimo stosowania tego sposobu porządkowania zawsze x odczytuje true.Prosze o pomoc. |
|
pekfos |
» 2013-06-02 13:01:05 operacja ładowania zmiennej x może odczytac false |
Wątek a najpierw zapisuje x, a potem y. Wątek b czeka, aż y będzie ustawione na true, a wtedy x też będzie ustawione na true, więc z zostaje zwiększone. z będzie inne od zera, więc asercja nie zakończy programu. |
|
fers334 Temat założony przez niniejszego użytkownika |
» 2013-06-02 14:38:25 Właśnie ja tez to tak rozumiem lecz w książce którą posiadam jest napisane tak :
asercja może wykazać błąd, ponieważ operacja ładowania zmiennej x może odczytac wartość false ,nawet jeśli operacja ładowania zmiennej y odczyta wartosc true i jesli operacja zapisu zmiennej x miała miejsce przed operacja zapisu zmiennej y.x i y to dwie różne zmienne , zatem widoczność wartości odczytywanych za pośrednictwem operacji na tych zmiennych nie podlega żadnym regułom i ograniczeniom kolejnosci. |
|
fers334 Temat założony przez niniejszego użytkownika |
» 2013-06-04 20:42:39 Rozumiem że nikt nie potrafi pomóc mi w nurtującej mnie sprawie, skoro tak to zamykam temat oraz dziękuje za próbę udzielenia pomocy.
Fers |
|
DejaVu |
» 2013-06-04 21:39:59 Skoro jesteś w gorącej wodzie kąpany... to trudno :) Ja przeglądam ostatnio tylko tematy nieaktywne dłużej niż 3 dni :) PS. void write_x_then_y() { x.store( true, std::memory_order_relaxed ); y.store( true, std::memory_order_relaxed ); } void read_y_then_x() { while( !y.load( std::memory_order_relaxed ) ); if( x.load( std::memory_order_relaxed ) ) ++z; }
PSS. http://en.cppreference.com/w/cpp/atomic/atomicEach instantiation and full specialization of the std::atomic template defines an atomic type. Objects of atomic types are the only C++ objects that are free from data races; that is, if one thread writes to an atomic object while another thread reads from it, the behavior is well-defined.
|
PSSS. Jeżeli czytasz polską książkę, to nie dziw się, że mogą być bezsensowne zdania, bo takie książki są z definicji tłumaczone, a nie pisane przez osobę techniczną. /edit: Dodam jeszcze: http://en.cppreference.com/w/cpp/atomic/memory_orderAtomic operations tagged std::memory_order_relaxed are not synchronization operations, they do not order memory. They only guarantee atomicity and modification order consistency. For example, with x and y initially zero,
r1 = y.load( memory_order_relaxed ); x.store( r1, memory_order_relaxed );
r2 = x.load( memory_order_relaxed ); y.store( 42, memory_order_relaxed );
is allowed to produce r1 == r2 == 42 because, although A is sequenced-before B and C is sequenced before D, nothing prevents D from appearing before A in the modification order of y, and B from appearing before C in the modification order of x. Updating the same global counter from multiple threads requires atomicity, but no synchronization or ordering
|
Więc operacje w każdym wątku są wykonywane sekwencyjnie, a jedynie nie ma gwarancji w którym momencie będą wykonywane dane linijki z każdego wątku (ale kolejność wykonywania linijek w każdym wątku jest znana). |
|
DejaVu |
» 2013-06-04 22:07:37 Hm... The rationale of this is that when several threads simultaneously read and write to several variables on multi-core systems, one thread might see the values change in different order than another thread has written them. |
Te różne tryby atomica faktycznie warto przestudiować... może w tej książce rację mają...? :P /edit: Ja bym eksperymentalnie zapuścił np. milion razy wykonanie tego kodu i sprawdził czy choć raz zachodzi Assert. Trochę jeszcze poczytałem na ten temat i... koniec końców najlepszym rozwiązaniem byłoby wzięcie kartki oraz rozpisanie każdego 'memory_order' tak, aby zauważyć i zrozumieć pomiędzy nimi różnice. /edit2: W każdym razie wydaje mi się nieco dziwne, aby zmienna modyfikowana później była 'synchronizowana' przed zmienną modyfikowaną wcześniej w tym samym wątku więc... coś tu się kupy zbytnio nie trzyma :) |
|
fers334 Temat założony przez niniejszego użytkownika |
» 2013-06-04 22:21:46 Wielkie dzięki no to zacznę kombinować.Jeszcze raz dzięki. |
|
DejaVu |
» 2013-06-04 22:27:38 Spoko, no ale poteoretyzujmy skoro taki ciekawy temat się trafił :P Załóżmy, że wykonam instrukcję A (modyfikuje x) i B (modyfikuje y). Drugi wątek wisi na instrukcji C (czyta y), więc w celu pójścia dalej musi albo poczekać na synchronizację albo wymusić ją. Więc jeżeli załóżmy wątek wymusi synchronizację tej jednej zmiennej (bo bez tego dalej nie pójdzie), to uzyskamy sytuację, w której wątek drugi widzi modyfikację instrukcji B ale nie widzi modyfikacji instrukcji A. Jednak później jest linijka odpytująca się o stan zmiennej x, więc teoretycznie powinno pójść wymuszenie synchronizacji instrukcji A. Jednak jeżeli zmienna podczas odczytywania nie wymusza synchronizacji to powstaje pytanie KTO decyduje o tym, kiedy nastąpi synchronizacja stanów zmiennych?
Wydaje mi się, że nie powinno dojść do sytuacji, w której zmienna modyfikowana później jest synchronizowana przed zmienną modyfikowaną wcześniej w tym samym wątku... bo gdzie tu jakiś sensowny determinizm, który można wykorzystać przy kodowaniu? |
|
« 1 » 2 |