Model pamięci Javy

Model pamięci Java opisuje sposób interakcji wątków w języku programowania Java poprzez pamięć. Wraz z opisem jednowątkowego wykonania kodu model pamięci dostarcza semantyki języka programowania Java.

Oryginalny model pamięci Java opracowany w 1995 roku był powszechnie postrzegany jako zepsuty, uniemożliwiający wiele optymalizacji środowiska wykonawczego i nie zapewniający wystarczająco silnych gwarancji bezpieczeństwa kodu. Został zaktualizowany w ramach Java Community Process jako żądanie specyfikacji Java 133 (JSR-133), które weszło w życie w 2004 r. dla Tiger (Java 5.0) .

Kontekst

Język programowania Java i platforma zapewniają możliwości wątków . Synchronizacja między wątkami jest niezwykle trudna dla programistów; trudność ta jest jeszcze większa, ponieważ aplikacje Java mogą działać na szerokiej gamie procesorów i systemów operacyjnych . Aby móc wyciągnąć wnioski na temat zachowania programu, projektanci języka Java zdecydowali, że muszą jasno zdefiniować możliwe zachowania wszystkich programów Java.

Na nowoczesnych platformach kod często nie jest wykonywany w kolejności, w jakiej został napisany. Jest ponownie porządkowany przez kompilator, procesor i podsystem pamięci, aby osiągnąć maksymalną wydajność. W wieloprocesorowych poszczególne procesory mogą mieć własne lokalne pamięci podręczne, które nie są zsynchronizowane z pamięcią główną. Zasadniczo niepożądane jest wymaganie, aby wątki pozostawały w idealnej synchronizacji ze sobą, ponieważ byłoby to zbyt kosztowne z punktu widzenia wydajności. Oznacza to, że w dowolnym momencie różne wątki mogą widzieć różne wartości dla tych samych udostępnionych danych.

W środowisku jednowątkowym łatwo jest uzasadnić wykonanie kodu. Typowe podejście wymaga, aby system zaimplementował szeregową dla poszczególnych wątków w izolacji. Gdy wykonywany jest pojedynczy wątek, będzie wyglądać tak, jakby wszystkie akcje podjęte przez ten wątek były wykonywane w kolejności, w jakiej pojawiają się w programie, nawet jeśli same akcje są wykonywane w innej kolejności.

Jeśli jeden wątek wykonuje swoje instrukcje poza kolejnością, inny wątek może zobaczyć fakt, że te instrukcje zostały wykonane poza kolejnością, nawet jeśli nie wpłynęło to na semantykę pierwszego wątku. Rozważmy na przykład dwa wątki z następującymi instrukcjami, wykonywane współbieżnie, gdzie zmienne x i y są inicjowane na 0:

Wątek 1 Wątek 2
x = 1; int r1 = y;
y = 2; int r2 = x;

Jeśli nie są wykonywane żadne zmiany kolejności, a odczyt y w wątku 2 zwraca wartość 2, to kolejny odczyt x powinien zwrócić wartość 1, ponieważ zapis do x został wykonany przed zapisem do y. Jeśli jednak kolejność dwóch zapisów zostanie zmieniona, odczyt y może zwrócić wartość 2, a odczyt x może zwrócić wartość 0.

Model pamięci Java (JMM) definiuje dopuszczalne zachowanie programów wielowątkowych, a zatem opisuje, kiedy takie zmiany kolejności są możliwe. Nakłada ograniczenia czasu wykonania na relacje między wątkami a pamięcią główną w celu uzyskania spójnych i niezawodnych aplikacji Java. Dzięki temu możliwe jest wnioskowanie o wykonywaniu kodu w środowisku wielowątkowym, nawet w obliczu optymalizacji przeprowadzanych przez kompilator dynamiczny, procesor (procesory) i pamięci podręczne.

Model pamięci

W przypadku wykonania pojedynczego wątku zasady są proste. Specyfikacja języka Java wymaga, aby wirtualna maszyna Java obserwowała w obrębie wątku semantykę seryjną. Środowisko wykonawcze (które w tym przypadku zwykle odnosi się do kompilatora dynamicznego, procesora i podsystemu pamięci) może wprowadzać wszelkie przydatne optymalizacje wykonania, o ile wynik izolowanego wątku jest dokładnie taki sam, jak byłoby, gdyby wszystkie instrukcje zostały wykonane w kolejności, w jakiej instrukcje wystąpiły w programie (zwanej także porządkiem programu).

Głównym zastrzeżeniem jest to, że semantyka „jak gdyby” szeregowa nie uniemożliwia różnym wątkom posiadania różnych widoków danych. Model pamięci zapewnia jasne wskazówki dotyczące tego, jakie wartości mogą być zwracane podczas odczytywania danych. Podstawowe zasady zakładają, że można zmienić kolejność poszczególnych akcji, o ile sekwencyjna semantyka wątku, a także akcje, które implikują komunikację między wątkami, takie jak nabycie lub zwolnienie blokady , upewnij się, że działania, które mają miejsce przed nimi, są widoczne dla innych wątków, które widzą ich skutki. Na przykład wszystko, co dzieje się przed zwolnieniem blokady, będzie widziane jako uporządkowane przed i widoczne dla wszystkiego, co dzieje się po kolejnym przejęciu tej samej blokady.

Z matematycznego punktu widzenia istnieje częściowy porządek zwany porządkiem zdarzeń przed wszystkimi akcjami wykonywanymi przez program. Porządek , który wydarzy się przed, obejmuje porządek programu; jeśli jedna akcja ma miejsce przed inną w kolejności programu, nastąpi przed drugą w kolejności zdarzeń . Ponadto zwolnienia i kolejne przejęcia blokad tworzą krawędzie na wykresie zdarzeń przed. Odczyt może zwrócić wartość zapisu, jeśli ten zapis jest ostatnim zapisem do tej zmiennej przed odczytem wzdłuż jakiejś ścieżki w zdarzeniach przed kolejności lub jeśli zapis nie jest uporządkowany w odniesieniu do odczytu w kolejności dzieje się przed .

Uderzenie

Model pamięci Java był pierwszą próbą dostarczenia kompleksowego modelu pamięci dla popularnego języka programowania. Było to uzasadnione rosnącą powszechnością systemów współbieżnych i równoległych oraz potrzebą dostarczenia narzędzi i technologii o jasnej semantyce dla takich systemów. Od tego czasu potrzeba modelu pamięci została szerzej zaakceptowana, a podobna semantyka została zapewniona dla języków takich jak C++ .

Zobacz też

Linki zewnętrzne