Я часто видел этот тип кода в проектах, где приложению требуется глобальный держатель данных, поэтому они используют статический синглтон, к которому может получить доступ любой поток.
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;
}
}
Я надеюсь, что легко увидеть, что происходит. Можно вызвать GlobalData.getInstance().getData()
в любое время в любом потоке. Если два потока вызывают setData() с разными значениями, даже если вы не можете гарантировать, какой из них «победит», меня это не беспокоит.
Но потокобезопасность здесь меня не волнует. Что меня беспокоит, так это видимость памяти. Всякий раз, когда в Java возникает барьер памяти, кэшированная память синхронизируется между соответствующими потоками. Барьер памяти возникает при прохождении синхронизаций, доступе к volatile-переменным и т.д.
Представьте себе следующий сценарий, происходящий в хронологическом порядке:
// Thread 1
GlobalData d = GlobalData.getInstance();
d.setData("one");
// Thread 2
GlobalData d = GlobalData.getInstance();
d.setData("two");
// Thread 1
String value = d.getData();
Возможно ли, что последнее значение value
в потоке 1 все еще может быть "one"
? Причина в том, что поток 2 никогда не вызывал никаких синхронизированных методов после вызова d.setData("two")
, поэтому никогда не было барьера памяти? Обратите внимание, что барьер памяти в этом случае возникает каждый раз, когда вызывается getInstance()
, потому что он синхронизирован.
One can call GlobalData.getInstance().getData() at any time on any thread. It's thread-safe so I'm not worried about that
, но на самом деле это не потокобезопасно именно из-за сценария, который вы описываете. Потокобезопасность заключается не только в том, чтобы видеть объект в несогласованном состоянии. Это также касается просмотра устаревших данных. - person yair   schedule 13.08.2013