Instrukcja reordering & happens-before relation w Javie [duplikat]
W książce Java współbieżność w praktyce, kilka razy powiedziano nam, że instrukcje naszego programu mogą być zmieniane przez kompilator, przez JVM w czasie wykonywania, a nawet przez procesor. Powinniśmy więc założyć, że uruchamiany program nie będzie miał instrukcji wykonywanych w dokładnie takiej samej kolejności, jak podaliśmy w kodzie źródłowym.
Jednak ostatni rozdział omawiający model pamięci Java zawiera listę happens-before reguły wskazujące, które instrukcje są zachowywane przez JVM. Pierwsza z tych zasad to:
- " reguła kolejności programu. Każda akcja w wątku dzieje się przed każdą akcją w tym wątku, która pojawia się później w kolejności programu."
Wierzę ,że "kolejność programów" odnosi się do kodu źródłowego.
Moje pytanie: zakładając tę regułę, zastanawiam się, jaką instrukcję można właściwie uporządkować.
"akcja" jest zdefiniowana następująco:
Model pamięci Java jest określony w kategoriach działań, które obejmują odczyt i zapis do zmiennych, blokady i odblokowanie monitorów oraz uruchamianie i łączenie z wątkami. JMM definiuje częściowe porządkowanie nazwane happens before dla wszystkich działań w programie. Aby zagwarantować, że wątek wykonujący akcję B może zobaczyć wyniki akcji A (niezależnie od tego, czy A i B występują w różnych wątkach), musi istnieć związek a przed A I B. W przypadku braku a dzieje się to przed zamówieniem między dwiema operacjami, JVM może dowolnie zmieniać ich kolejność.
Inne wymienione reguły porządkowe to:
- zasada blokady monitora. Odblokowanie blokady monitora następuje przed każdą kolejną blokadą tej samej blokady monitora.
- zmienna zmienna zmienna. Zapis do pola lotnego następuje przed każdym kolejnym odczytem tego samego pola.
- zasada rozpoczęcia wątku. Wezwanie do wątku.start na wątku dzieje się przed każdą akcją w rozpoczęty wątek.
- zasada zakończenia wątku. Każda akcja w wątku dzieje się zanim jakikolwiek inny wątek wykryje, że wątek został zakończony, albo przez pomyślny powrót z wątku.Dołącz lub przez wątek.isAlive zwraca false.
- zasada przerwania. Wątek wywołujący przerwanie na innym wątku dzieje się zanim przerwany wątek wykryje przerwanie (albo przez wyrzucenie InterruptedException, albo wywołanie jest przerwane lub przerwane).
- reguła Finalizera. Koniec a konstruktor dla obiektu dzieje się przed rozpoczęciem finalizatora dla tego obiektu.
- przechodniość. Jeśli A dzieje się przed B, A B dzieje się przed C, to a dzieje się przed C.
1 answers
Kluczowym punktem reguły kolejności programu jest: w wątku.
Wyobraź sobie ten prosty program (wszystkie zmienne początkowo 0):
T1:
x = 5;
y = 6;
T2:
if (y == 6) System.out.println(x);
Z punktu widzenia T1, wykonanie musi być zgodne z y przypisanym po x (kolejność programu). Jednak z punktu widzenia T2 nie musi tak być i T2 może wydrukować 0.
T1 może przypisać y jako pierwsze, ponieważ 2 przypisania są niezależne i ich Zamiana nie wpływa na wykonanie T1.
Przy odpowiedniej synchronizacji, T2 zawsze wydrukuje 5 lub nic.
EDIT
Wydaje się, że źle interpretujesz znaczenie porządku programu. reguła kolejności programu sprowadza się do :
Jeśli
x
iy
są działaniami tego samego wątku ix
jest poprzedzoney
w porządku programu, tohb(x, y)
(tj.x
happens-beforey
).
happens-before ma bardzo specyficzne znaczenie w JMM. W szczególności, to nie oznacza, że y=6
musi być po x=5
W T1 z perspektywy zegara ściennego. Oznacza to tylko, że sekwencja działań wykonywanych przez T1 musi być zgodna z tej kolejności. Możesz również odnieść się do JLS 17.4.5:
Należy zauważyć, że obecność związku między dwoma czynnościami nie z konieczności oznacza, że muszą one odbywać się w tej kolejności w realizacji . Jeśli zmiana kolejności daje wyniki zgodne z prawem wykonania, nie jest nielegalne.
W przykładzie, który podałem powyżej, zgodzisz się, że z perspektywy T1 (tj. w programie z pojedynczym wątkiem), {[11] } jest zgodne z y=6;x=5;
, ponieważ nie odczytujesz wartości. Oświadczenie na następnej linii jest gwarantowane, W T1, aby zobaczyć te 2 działania, niezależnie od kolejności, w jakiej były wystąpili
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-21 11:42:25