Związek między instrukcjami kodu bajtowego a operacjami procesora
Specyfikacja Java gwarantuje, że pierwotne przypisania zmiennych są zawsze atomowe (oczekuj nalong
i podwójnietypes
.
Przeciwnie,Pobierz i dodaj operacja odpowiadająca słynnemui++
operacja inkrementacji byłaby nieatomowa, ponieważ prowadzi do operacji odczytu i modyfikacji-zapisu.
Zakładając ten kod:
public void assign(int b) {
int a = b;
}
Wygenerowany kod bajtowy to:
public void assign(int);
Code:
0: iload_1
1: istore_2
2: return
Widzimy więc, że zadanie składa się zdwa kroki (ładowanie i przechowywanie).
Zakładając ten kod:
public void assign(int b) {
int i = b++;
}
Kod bajtowy:
public void assign(int);
Code:
0: iload_1
1: iinc 1, 1 //extra step here regarding the previous sample
4: istore_2
5: return
Wiedząc, że procesor X86 może (przynajmniej nowoczesny), operować przyrostowo w sposób atomowy, jak powiedziano:
W informatyce instrukcja CPU do pobierania i dodawania jest specjalną instrukcją, która atomowo modyfikuje zawartość lokalizacji pamięci. Służy do implementacji algorytmów wzajemnego wykluczania i współbieżności w systemach wieloprocesorowych, generalizacji semaforów.
Zatem pierwsze pytanie: Pomimo tego, że kod bajtowy wymaga obu kroków (ładowania i przechowywania), czy Java opiera się na fakcie, że operacja przypisania jest operacją przeprowadzaną zawsze atomowo, niezależnie od architektury procesora, a zatem może zapewnić stałą atomowość (dla pierwotnych przypisań) w specyfikacji?
Drugie Pytanie: Czy błędem jest potwierdzanie, że przy bardzo nowoczesnym procesorze X86 i bez współdzielenia skompilowanego kodu na różnych architekturach nie ma potrzeby synchronizowaniai++
operacja (lubAtomicInteger
)? Biorąc pod uwagę, że jest już atomowy.