Mam strukturę danych, która składa się z połączonych węzłów. Możesz myśleć o niej jak o prostej liście powiązań. Każdy węzeł listy składa się z pewnej wartości i następnego pola wskazującego drugi węzeł lub wartość null, jeśli jest to ostatni węzeł. Pierwszy węzeł działa jako root, nie ma żadnej wartości, która wskazuje tylko na następny węzeł. Wszystkie pozostałe węzły są praktycznie niezmienne, a mianowicie, gdy nie zostaną stworzone ani ich wartość, ani ich następna zmiana pola podczas życia, chyba że struktura zostanie usunięta, co odnosi się do konkretnej sytuacji.Zmienne lotne i bariera pamięci w java
Jeden (tylko jeden) wątek dodaje nowe węzły z przodu listy. Osiąga się to przez skonstruowanie nowego obiektu, ustawienie jego pól i ustawienie następnego pola na obiekt wskazany przez root, a następnie ustawienie następnego pola głównego korzenia do tego nowego węzła.
Pozostałe węzły przeglądają strukturę, wykonując tylko odczyty. Mają odniesienie do węzła głównego, następnie przechodzą przez inne węzły, dopóki nie znajdą tego, czego szukają lub nie dojdą do końca listy.
Moje pytanie brzmi: czy wystarczy, aby kolejna zmienna była niestabilna? Z mojego rozumienia modelu pamięci Java, jeśli wątek główny (ten, który dodaje nowe węzły), wykona lotny zapis podczas dodawania nowego węzła, wtedy wszystko zostanie zsynchronizowane dokładnie i nie wystąpią niespójności.
Czy można założyć, że na podstawie architektury x86 odczyt zmiennych lotnych nie spowoduje pogorszenia wydajności? Ponieważ inne wątki często przeglądają strukturę czytając kolejne pole, ważne jest, aby można to było zrobić bez żadnych barier pamięci itp.
Mam również jeszcze jeden problem. Wątki, które będą przeglądać strukturę, będą również zawierać kilka dodatkowych węzłów. Węzły te będą całkowicie wątkowo-lokalne, a więc będą używane tylko przez wątek, który je utworzył i nie będą w ogóle udostępniane. Dla tych dodatkowych węzłów niepotrzebne jest, aby następne pole było niestabilne. Ponadto ustawienie zmiennego następnego pola spowoduje barierę pamięci, która spowoduje niepożądaną utratę wydajności. Zastanawiam się, czy istnieje sposób, aby tego uniknąć. Idealnie byłoby idealnie, gdyby następne pole działało czasami jako zmienne pole, a czasem jako normalne pole;) lub gdybym miał pełną kontrolę i mógł samodzielnie tworzyć bariery pamięci, kiedy tylko potrzebuję.
Edit:
Ja też zastanawiałem byłoby możliwe jakoś zsynchronizować wszystkie te pisze na innej zmiennej lotnych? Na przykład inne zupełnie niezwiązane ze sobą zmienne statyczne? Skoro lotne zapisy przepłukują wszystkie oczekujące zapisy, czy następne pole nie byłoby niestabilne i zamiast tego inna zmienna lotna byłaby napisana po tym, jak wątek aktualizujący wykona całą pracę?
Nie wydaje mi się to zbyt bezpieczne, ponieważ nie ma żadnych zdarzeń przed relacją i poprzednie zapisy mogą zostać ponownie uporządkowane. Można przypisać następne przypisania pól za pomocą przypisań pól wartości prowadzących do powtarzających się wątków obserwujących niespójny stan obiektu.
Ale może uda się stworzyć taki system, który byłby bezpieczny?Jak o tym:
aktualizacja wątku najpierw konstruuje nowy obiekt, inicjalizuje jego pola wartości, ustawia następne pole do węzła wskazanego przez węzeł główny, wykonuje lotny zapis na pewnej zmiennej statycznej, ustawia następne pole węzła głównego do nowo utworzonego węzła
+1. Fajne wyjaśnienie semantyki "volatile" w semestrze pamięciowym, chociaż należy podkreślić, że maszyny JVM przed JSR133 (tj. Java <5.0) nie miały tej samej semantyki ... – thkala
Dobra uwaga dzięki za dołączenie jako uwagi. –
Dzięki za wspaniałą odpowiedź. Mam nadzieję, że dobrze zrozumiałeś, co się dzieje w moim kodzie. Nie ma odniesienia do katalogu głównego, a jedynie węzeł główny. Dlatego ustawiam dwa kolejne pola (jeden z nowych obiektów i jeden z węzłów głównych). – ciamej