2013-03-12 13 views
10

Jawa, gdy mają dwa wątki dzielące następujących zmiennych:Co naprawdę robi bariera LoadLoad?

int a; 
volatile int b; 

jeśli gwint 1 służy:

a = 5; 
b = 6; 

Następnie bariera StoreStore umieszcza się pomiędzy tymi dwoma instrukcjami i „a”, to jest przepłukane z powrotem do pamięci głównej.

Teraz, jeśli nić 2 nie jest:

if(b == 6) 
a++; 

LoadLoad barierowa jest umieszczona pomiędzy i mieć gwarancję, że jeżeli nowa wartość „b” jest widoczny następnie nową wartość „a” jest widoczny, a także . Ale jak właściwie to się dzieje? Czy LoadLoad unieważnia pamięć podręczną/rejestry CPU? Lub po prostu instruuje CPU, aby pobrać wartości zmiennych, które następują po odczytaniu z lotnego ponownie z procesora?

I znaleźć informacji na temat LoadLoad bariery (http://gee.cs.oswego.edu/dl/jmm/cookbook.html):

LoadLoad barier SEKWENCJI: Load1; LoadLoad; Load2 zapewnia, że ​​dane Load1 zostaną wczytane przed dostępem do danych przez Load2, a wszystkie załadowane instrukcje kolejnych obciążeń . Ogólnie rzecz biorąc, bariery LoadLoad są potrzebne w przypadku procesorów, które wykonują obciążenia spekulacyjne i/lub przetwarzania poza kolejnością, w którym instrukcje odczytywania obciążenia mogą omijać magazyny oczekujące. Na procesorach, które gwarantują zawsze zachowanie porządku ładunków, bariery te wynoszą zero.

, ale tak naprawdę nie wyjaśnia, w jaki sposób zostało to osiągnięte.

+0

Odpowiedź zależy od architektury procesora - ten sam dokument ma tabelę z każdą instrukcją procesora, która pokazuje, że 'LoadLoad' na przykład jest bez op. Na x86. – assylias

+0

to jak to działa? Mam na myśli, po StoreStore wartości są spłukiwane z powrotem do pamięci. Ale w jaki sposób wątek 2 powinien je zobaczyć? Jeśli LoadLoad oceniany jest jako "no-op", wątek 2 może nadal używać wartości buforowanych. – Janek

+0

, ponieważ model pamięci procesora jest wystarczająco silny, aby zagwarantować, że tak się stanie. Próbuję powiedzieć, że Java składa obietnicę, że jeśli użyjesz niestabilności, coś się nie stanie. Sposób implementacji w JVM zależy od procesora i wykorzystuje instrukcje ad hoc (lub brak instrukcji, jeśli jest to istotne). Więcej informacji na temat punktu LoadLoad/x86 można znaleźć tutaj: http://altair.cs.oswego.edu/pipermail/concrency-interest/2012-July/009615.html – assylias

Odpowiedz

3

Podam jeden przykład, jak to osiągnąć. Możesz przeczytać więcej o szczegółach here. Dla procesorów x86, jak wskazałeś LoadLoad kończy jako no-ops. W artykule związane Mark zauważa, że ​​

Doug wymienia StoreStore, LoadLoad i LoadStore

Tak w istocie jedyną barierą jest potrzebna dla architektur x86 StoreLoad. Jak to osiągnąć na niskim poziomie?

Jest to fragment z bloga:

Oto kod jest generowany zarówno lotnych i nielotnych brzmi:

nop      ;*synchronization entry 
mov 0x10(%rsi),%rax ;*getfield x 

I dla zapisu lotnych:

xchg %ax,%ax 
movq $0xab,0x10(%rbx) 
lock addl $0x0,(%rsp)  ;*putfield x 

Instrukcja lock to StoreLoad zgodnie z listą Douga dla c ookbook.Ale dyspozycja blokady synchronizuje również wszystkie odczyty z innymi procesami jako listed

Zablokowany instrukcje mogą być wykorzystane do synchronizacji danych napisany przez jednego procesora i odczytywane przez inny procesor.

Zmniejsza to obciążenie związane z koniecznością wprowadzenia barier LoadStore LoadLoad dla lotnych ładunków.

Wszystko, co jest powiedziane, powtórzę, co zauważyłem assylias. Sposób, w jaki to się dzieje, nie powinien być ważny dla programisty (jeśli interesuje Cię inny programista/programista kompilatora). volatile słowo kluczowe jest rodzajem interfejsu mówiąc

  1. Otrzymasz najbardziej aktualne czytać co jest napisane przez innego wątku
  2. nie dostaniesz spalone przez optymalizacje kompilatora JIT.
+0

Ładny link. Chciałbym powtórnie sformułować: "* Otrzymasz najbardziej aktualny odczyt, który jest napisany przez inny wątek *" => "* W końcu zobaczysz zapisy, gdy później czytasz z zmiennej lotnej -" ostatecznie ", co oznacza niemal natychmiast w praktyce * ";-) – assylias

+0

Właściwie, ważne jest, jeśli interesuje Cię, na jakim sprzęcie aplikacja działa najszybciej lub jak osiągnąć najwyższą wydajność. Mieliśmy nadzieję na skorzystanie z cztero-gniazdowego Xeona (64 SMT) o wiele bardziej niż my w końcu. Jeśli nie masz kontroli nad sprzętem lub działa tylko na pojedynczych gniazdach, może to nie być problem, ale szczegóły implementacji współbieżności i ich wpływ na skalowalność na większych komputerach mogą z pewnością wpłynąć na projekt, jeśli są znane na wczesnym etapie. –

+0

@RalfH Mówiłem w imieniu przeciętnego programisty używając słowa kluczowego 'volatile'. Mówiąc ogólnie, deweloper nie musi martwić się o to, jak bardzo zmienna jest zaimplementowana.Czy zauważyłeś instancję, która wiedząc, że architektura bazowa zmienia sposób użycia zmiennej w inny sposób? –

0

Jeśli wartość obciążenia LoadLoad jest równa zero, wątek 2 może nadal używać wartości buforowanych.

Jest to objęte tabelą "Zamówienie" w książce kucharskiej.

Kolejność programowania jest

read b 
read a 
write a 

przez "buforowania", to znaczy, że kod jest kolejność

read a 
... 
read b 

Ta zmiana kolejności jest zabronione.

+0

Właściwie oznaczałem prawdziwe buforowanie w pamięci podręcznej procesora, a nie porządkowanie instrukcji. – Janek

+0

ładunek jest obciążeniem, nie będzie czytany z rejestrów procesora. – ZhongYu

+0

@zhong Myślę, że obawą Janka było, "jak pole może być aktualne w rejestrze procesora, jeśli nigdy nie inicjuje obciążenia po zapisie przez innego procesora". –