Widziałem ten typ kodu dużo w projektach, w których aplikacja chce globalnego posiadacza danych, więc używają statycznego singletonu, do którego ma dostęp każdy wątek.Czym jest widoczność pamięci dla zmiennych, do których dostęp jest uzyskiwany w statycznych singletonach w języku Java?
public class GlobalData {
// Data-related code. This could be anything; I've used a simple String.
//
private String someData;
public String getData() { return someData; }
public void setData(String data) { someData = data; }
// Singleton code
//
private static GlobalData INSTANCE;
private GlobalData() {}
public synchronized GlobalData getInstance() {
if (INSTANCE == null) INSTANCE = new GlobalData();
return INSTANCE;
}
}
Mam nadzieję, że łatwo będzie zobaczyć, co się dzieje. W dowolnym momencie można wywołać GlobalData.getInstance().getData()
w dowolnym wątku. Jeśli dwa wątki wywołują setData() z różnymi wartościami, nawet jeśli nie możesz zagwarantować, który z nich "wygrywa", nie martwię się tym.
Ale bezpieczeństwo wątków nie jest tutaj moim problemem. Martwię się tylko o widoczność pamięci. Ilekroć w Javie jest bariera pamięci, pamięć podręczna jest zsynchronizowana pomiędzy odpowiednimi wątkami. Bariera pamięci zdarza się podczas przechodzenia przez synchronizacji, dostęp do zmiennych lotnych itp
Wyobraźmy sobie następującą scenariusz dzieje się w porządku chronologicznym:
// Thread 1
GlobalData d = GlobalData.getInstance();
d.setData("one");
// Thread 2
GlobalData d = GlobalData.getInstance();
d.setData("two");
// Thread 1
String value = d.getData();
nie jest to możliwe, że ostatnia wartość value
w wątku 1 puszka nadal być "one"
? Powodem jest, że wątek 2 nigdy nie wywoływał żadnych zsynchronizowanych metod po wywołaniu d.setData("two")
, więc nigdy nie było bariery pamięci? Zauważ, że bariera pamięci w tym przypadku dzieje się za każdym razem, gdy wywoływana jest getInstance()
, ponieważ jest zsynchronizowana.
Mówisz: "Można wywołać GlobalData.getInstance(). GetData() w dowolnym momencie na dowolnym wątku. Jest bezpieczny dla wątków, więc nie martwię się o to ", ale w rzeczywistości nie jest bezpieczny dla wątków dokładnie ze względu na opisywany scenariusz. Bezpieczeństwo wątków to nie tylko obserwowanie obiektu w niespójnym stanie. Chodzi także o oglądanie nieaktualnych danych. – yair
@yair Tak, ale naprawdę próbowałem zbadać aspekt widoczności pamięci w przeciwieństwie do niespójnych stanów na podstawie wykonania synchronicznego. –