Да, это необходимо. Есть несколько методов, которые можно использовать для достижения безопасности потока с отложенной инициализацией:
Драконовских синхронизации:
private static YourObject instance;
public static synchronized YourObject getInstance() {
if (instance == null) {
instance = new YourObject();
}
return instance;
}
Этим решение требует, чтобы каждого нити быть синхронизирована, когда в действительности только первые несколько должно быть.
Double check synchronization:
private static final Object lock = new Object();
private static volatile YourObject instance;
public static YourObject getInstance() {
YourObject r = instance;
if (r == null) {
synchronized (lock) { // While we were waiting for the lock, another
r = instance; // thread may have instantiated the object.
if (r == null) {
r = new YourObject();
instance = r;
}
}
}
return r;
}
Это решение гарантирует, что только первые несколько потоков, которые пытаются получить ваш синглтон должны пройти через процесс приобретения замка.
Initialization on Demand:
private static class InstanceHolder {
private static final YourObject instance = new YourObject();
}
public static YourObject getInstance() {
return InstanceHolder.instance;
}
Это решение имеет преимущество гарантий модели памяти Java-о инициализации класса для обеспечения безопасности потоков. Каждый класс может быть загружен только один раз, и он будет загружен только тогда, когда это необходимо. Это означает, что при первом вызове getInstance
будет загружено InstanceHolder
и будет создано instance
, и поскольку это контролируется ClassLoader
s, дополнительная синхронизация не требуется.
Имейте в виду, что Singleton - это анти-шаблон: http://www.yegor256.com/2016/06/27/singletons-must-die.html – yegor256