Здравствуйте, StanislavK, Вы писали:
SK>Здравствуйте, PZI, Вы писали:
A>>>>>Есть известная реализация синглтона PZI>>>>Вот просто интересно, а кто нибудь вообще пишет синглетоны используя double check locking? SK>>>Почему бы и нет? PZI>>эм... ну скажем так, возможная выгода от его использования очень мала, в сравнении с другими варантами реализации синглетона. SK>А какими другими? Без контекста очень трудно
Ну хотя бы такое, если уж совсем приперло инициализацию по дерганью метода сделать.
final class Singleton {
private static volatile Singleton instance;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
Но товарищ Allen Holub заметил, что использование volatile модификатора может привести к проблемам производительности на мультипроцессорных системах.
Покритикуйте использование не блокирющего алгоритма взамен синхронизации, например:
final class NonBlockSingleton {
private static final AtomicReference<NonBlockSingleton> ref = new AtomicReference<NonBlockSingleton>();
public static NonBlockSingleton getInstance() {
if (ref.get() == null) {
NonBlockSingleton instance = null;
do {
instance = new NonBlockSingleton();
} while (ref.compareAndSet(null, instance));
}
return ref.get();
}
}
Здравствуйте, Alstresh, Вы писали:
A>Покритикуйте использование не блокирющего алгоритма взамен синхронизации, например:
Два параллельных потока у вас создают 2 экземпляра.
Здравствуйте, Blazkowicz, Вы писали:
B>Здравствуйте, Alstresh, Вы писали:
A>>Покритикуйте использование не блокирющего алгоритма взамен синхронизации, например: B>Два параллельных потока у вас создают 2 экземпляра.
Да, там перемудрил, а если так:
final class NonBlockSingleton {
private static final AtomicReference<NonBlockSingleton> ref = new AtomicReference<NonBlockSingleton>();
public static NonBlockSingleton getInstance() {
if (ref.get() == null) {
ref.compareAndSet(null, new NonBlockSingleton());
}
return ref.get();
}
}
A>final class NonBlockSingleton {
A> private static final AtomicReference<NonBlockSingleton> ref = new AtomicReference<NonBlockSingleton>();
A> public static NonBlockSingleton getInstance() {
A> if (ref.get() == null) {
A> NonBlockSingleton instance = null;
A> do {
A> instance = new NonBlockSingleton();
A> } while (ref.compareAndSet(null, instance));
A> }
A> return ref.get();
A> }
A>}
A>
Мне кажется, что из N потоков прошедших проверку if (ref.get() == null), N-1 поток из do..while не выйдут никогда.
Здравствуйте, Alstresh, Вы писали:
A>Есть известная реализация синглтона A>Покритикуйте использование не блокирющего алгоритма взамен синхронизации, например:
Подобная оптимизиация, кроме всего прочего, ещё и лишена смысла. Подумайте логически, без кода, какого именно поведения вы хотите добиться. Что именно оптимизируется?
Здравствуйте, Blazkowicz, Вы писали:
B>Здравствуйте, Alstresh, Вы писали:
A>>Есть известная реализация синглтона A>>Покритикуйте использование не блокирющего алгоритма взамен синхронизации, например: B>Подобная оптимизиация, кроме всего прочего, ещё и лишена смысла. Подумайте логически, без кода, какого именно поведения вы хотите добиться. Что именно оптимизируется?
А что здесь то же самое? Открываем javadoc
Atomically sets the value to the given updated value if the current value == the expected value.
boolean java.util.concurrent.atomic.AtomicReference.compareAndSet(NonBlockSingleton expect, NonBlockSingleton update)
Т.о если два потока одновременно попытаються создать инстанс, то создаст только один из них, а второй отвалиться по условию "current value == the expected value". Я хочу избавиться от блjкирующего алгоритма и volatile
A>Но товарищ Allen Holub заметил, что использование volatile модификатора может привести к проблемам производительности на мультипроцессорных системах. A>Покритикуйте использование не блокирющего алгоритма взамен синхронизации, например: A>
A>final class NonBlockSingleton {
A> private static final AtomicReference<NonBlockSingleton> ref = new AtomicReference<NonBlockSingleton>();
A> public static NonBlockSingleton getInstance() {
A> if (ref.get() == null) {
A> NonBlockSingleton instance = null;
A> do {
A> instance = new NonBlockSingleton();
A> } while (ref.compareAndSet(null, instance));
A> }
A> return ref.get();
A> }
A>}
A>
Че-то я не понял. Ты в исходники не смотрел?
java.util.concurrent.atomic.AtomicReference#value:
private volatile V value;
Думаю, что товарищ Allen Holub говорил о несколько ином контексте. Кстати, а можно ссылку на первоисточник?
Здравствуйте, PZI, Вы писали:
A>>Есть известная реализация синглтона PZI>Вот просто интересно, а кто нибудь вообще пишет синглетоны используя double check locking?
Почему бы и нет?
Здравствуйте, StanislavK, Вы писали:
SK>Здравствуйте, PZI, Вы писали:
A>>>Есть известная реализация синглтона PZI>>Вот просто интересно, а кто нибудь вообще пишет синглетоны используя double check locking? SK>Почему бы и нет?
эм... ну скажем так, возможная выгода от его использования очень мала, в сравнении с другими варантами реализации синглетона.
Здравствуйте, PZI, Вы писали:
A>>>>Есть известная реализация синглтона PZI>>>Вот просто интересно, а кто нибудь вообще пишет синглетоны используя double check locking? SK>>Почему бы и нет? PZI>эм... ну скажем так, возможная выгода от его использования очень мала, в сравнении с другими варантами реализации синглетона.
А какими другими? Без контекста очень трудно
Здравствуйте, StanislavK, Вы писали:
PZI>>Вот просто интересно, а кто нибудь вообще пишет синглетоны используя double check locking? SK>Почему бы и нет?
Потому что ClassLoading в Java и так ленивый и потокобезопасный. В чем бенефит double check locking?
A>final class NonBlockSingleton {
A> private static final AtomicReference<NonBlockSingleton> ref = new AtomicReference<NonBlockSingleton>();
A> public static NonBlockSingleton getInstance() {
A> if (ref.get() == null) {
A> NonBlockSingleton instance = null;
A> do {
A> instance = new NonBlockSingleton();
A> } while (ref.compareAndSet(null, instance));
A> }
A> return ref.get();
A> }
A>}
A>
В AtomicReference тот же volatile и используется. Так что, учитывая что конструктор у тебя будет вызваться каждый раз, то непонятная какая тут оптимизация.
Избавиться от волатайл можно двумяя способами.
1. Можно его не висать если все поля в синглноне final. Тогда проблем с синглтоном не будет.
2. Использовать inner static holder.
Здравствуйте, PZI, Вы писали: PZI>Здравствуйте, StanislavK, Вы писали: SK>>Здравствуйте, PZI, Вы писали: PZI>>>>>Вот просто интересно, а кто нибудь вообще пишет синглетоны используя double check locking? SK>>>>Почему бы и нет? PZI>>>эм... ну скажем так, возможная выгода от его использования очень мала, в сравнении с другими варантами реализации синглетона. SK>>А какими другими? Без контекста очень трудно PZI>Ну хотя бы такое, если уж совсем приперло инициализацию по дерганью метода сделать.
Ах, вот почему…
Мне видится по крайней мере одно преимущество double check locking по сравнению с initialization on demand holder — меньше размер байткода на сотню-две байт. Для J2ME или апплетов играет.
Здравствуйте, gegMOPO4, Вы писали:
MOP>Мне видится по крайней мере одно преимущество double check locking по сравнению с initialization on demand holder — меньше размер байткода на сотню-две байт. Для J2ME или апплетов играет.
В J2ME и апплетах с многопоточностью попроще.
Здравствуйте, Blazkowicz, Вы писали:
B>Здравствуйте, StanislavK, Вы писали:
PZI>>>Вот просто интересно, а кто нибудь вообще пишет синглетоны используя double check locking? SK>>Почему бы и нет? B>Потому что ClassLoading в Java и так ленивый и потокобезопасный. В чем бенефит double check locking?
Вообще, да, он достаточно ленивый, чтобы не загружать класс пока он реально не используется. В теории может быть такое, когда класс загружен, но инстанс еще нужен, хотя это не часто.
Здравствуйте, PZI, Вы писали:
PZI>Здравствуйте, StanislavK, Вы писали:
SK>>Здравствуйте, PZI, Вы писали:
A>>>>>>Есть известная реализация синглтона PZI>>>>>Вот просто интересно, а кто нибудь вообще пишет синглетоны используя double check locking? SK>>>>Почему бы и нет? PZI>>>эм... ну скажем так, возможная выгода от его использования очень мала, в сравнении с другими варантами реализации синглетона. SK>>А какими другими? Без контекста очень трудно
PZI>Ну хотя бы такое, если уж совсем приперло инициализацию по дерганью метода сделать.
Не, ну можно. А зачем? По количеству строк не сильно отличается от double-locking. Ну и потом еще эта ExceptionInInitializerError, которой болеют все синглетоны такого типа. Получается, что реально вылетает совсем не то исключение, которое кидает конструктор.
Здравствуйте, StanislavK, Вы писали:
SK>Не, ну можно. А зачем? По количеству строк не сильно отличается от double-locking.
Безопаснее. Даже на старых версиях JVM.
SK>Ну и потом еще эта ExceptionInInitializerError, которой болеют все синглетоны такого типа. Получается, что реально вылетает совсем не то исключение, которое кидает конструктор.
ExceptionInInitializerError всегда содержит Cause
Здравствуйте, Blazkowicz, Вы писали:
B>Здравствуйте, StanislavK, Вы писали:
SK>>Не, ну можно. А зачем? По количеству строк не сильно отличается от double-locking. B>Безопаснее. Даже на старых версиях JVM.
Безопаснее только на старых версиях. Начиная с 1.5, насколько мне известно, проблем нет.
SK>>Ну и потом еще эта ExceptionInInitializerError, которой болеют все синглетоны такого типа. Получается, что реально вылетает совсем не то исключение, которое кидает конструктор. B>ExceptionInInitializerError всегда содержит Cause
конечно содержит, но выглядеть это будет уже не так хорошо. Все "красоты" такого синглетона в этом случае как-то вяло смотрятся.
Здравствуйте, StanislavK, Вы писали:
SK>Вообще, да, он достаточно ленивый, чтобы не загружать класс пока он реально не используется. В теории может быть такое, когда класс загружен, но инстанс еще нужен, хотя это не часто.
Это решается вложеным классов. PZI привел ссылку выше.
Здравствуйте, StanislavK, Вы писали:
SK>Здравствуйте, PZI, Вы писали:
PZI>>Здравствуйте, StanislavK, Вы писали:
SK>>>Здравствуйте, PZI, Вы писали:
SK>Не, ну можно. А зачем? По количеству строк не сильно отличается от double-locking. Ну и потом еще эта ExceptionInInitializerError, которой болеют все синглетоны такого типа. Получается, что реально вылетает совсем не то исключение, которое кидает конструктор.
Ну хоть и не сильно, но отличается. И дело даже не в количестве строчек как токавых, а в наличии на пустом месте двух if -ов. Ну это может конечно только мне не нравится такое...
Во вторых, проще для понимания. Вот чисто моё ИМХО — 98% тех, кто знает DCL, не понимают для чего там volatile. Точнее они уверенны что знают, но это знание обычно ошибочно. А это плохо, когда пишут и не понимают для чего.
Единственный недостаток статик холдера — это если наш синглетон упадет при создании, то второй раз он уже не создастся. Но как часто это является определяющим фактором при выборе способе реализации синглетона? Я думаю совсем не часто...
Здравствуйте, PZI, Вы писали:
SK>>Не, ну можно. А зачем? По количеству строк не сильно отличается от double-locking. Ну и потом еще эта ExceptionInInitializerError, которой болеют все синглетоны такого типа. Получается, что реально вылетает совсем не то исключение, которое кидает конструктор.
PZI>Ну хоть и не сильно, но отличается. И дело даже не в количестве строчек как токавых, а в наличии на пустом месте двух if -ов. Ну это может конечно только мне не нравится такое... PZI>Во вторых, проще для понимания. Вот чисто моё ИМХО — 98% тех, кто знает DCL, не понимают для чего там volatile. Точнее они уверенны что знают, но это знание обычно ошибочно. А это плохо, когда пишут и не понимают для чего. PZI>Единственный недостаток статик холдера — это если наш синглетон упадет при создании, то второй раз он уже не создастся. Но как часто это является определяющим фактором при выборе способе реализации синглетона? Я думаю совсем не часто...
В общем согласен. Я ваще все это к тому, что однозначно нельзя сказать, что то или это лучше в общем случае. Как говорится, кому, что и когда как.
Начсет volatile, то надо больно бить тех кто не понимает и пишет мультипоточные аппликухи