JavaRush /Java блог /Архив info.javarush /Какой сиглтон лучше всего использовать при синхронизации?...
noxior
30 уровень
London

Какой сиглтон лучше всего использовать при синхронизации?

Статья из группы Архив info.javarush
в целом понятно что тут к чему. Только есть оговорки о особенностях применения синхронизации. Мне просто хотелось бы услышать мнение о достоинствах и недостатках их, что и в каких случаях лучше всего использовать. вот самый обычный способ... package com.journaldev.singleton; public class ThreadSafeSingleton { private static ThreadSafeSingleton instance; private ThreadSafeSingleton(){} public static synchronized ThreadSafeSingleton getInstance(){ if(instance == null){ instance = new ThreadSafeSingleton(); } return instance; } } способ ниже был описан на хабре, и на том же хабре писалось что он не работает(прилагалась статья на инглише, но я пока не силен в этом(), подскажет кто что тут не так? public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){ if(instance == null){ synchronized (ThreadSafeSingleton.class) { if(instance == null){ instance = new ThreadSafeSingleton(); } } } return instance; } и вот тоже есть способ синхронизации через статический метод, в чем его плюс? где лучше использовать? public class Solution { public static class OurPresident { private static OurPresident president; static { synchronized (OurPresident.class) { president = new OurPresident(); } } private OurPresident() { } public static OurPresident getOurPresident() { return president; } } }
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
HansNoodles Уровень 31
5 мая 2016
Способ который ты называл самым обычным — неплох, но имеет недостатки в быстродействии, связанные с тем что метод getInstance синхронизирован и не может быть использован различными потоками одновременно.

Реализация метода getInstance через DCL(double checked locking) существенно улучшает производительность, т.к. уже нет ограничения на количество потоков в методе getInstance(). В данном случае алгоритм работы такой:
1)Проверяем было ли инициализировано поле instance, и если да, то вернем его.
2)Если же поле instance не было инициализировано, то необходимо захватить лок класса Singleton, создать объект, присвоить его полю instance и вернуть.
Синхронизация в данном случае жизненно необходима, чтобы избежать возможности создания дубликатов объекта класса Singleton при выполнении кода в многопоточном окружении. Ускорение же, достигается тем, что после того как объект был создан, сколько угодно потоков сможет зайти в метод getIntance и получить значение поля instance.
Проблема с DCL заключается в том, что у нас нет гарантий того в каком порядке будут выполнены низкоуровневые операции по работе с памятью. В частности возможен следующий сценарий:
1) Поток А входит в метод getInstance, видит что поле instance равно null и переходит в статический блок для его инициализации.
2) Поток B входит в метод getInstance, но т.к. он пока не находится в синхронизированном блоке кода — он может видеть низкоуровневые операции по выделению памяти, созданию объекта и присваиванию ссылки на объект полю instance в произвольном порядке. В частности возможен вариант, когда поток B «успеет увидеть» выделение памяти и присваивание ссылки полю instance, но конструктор будет выполнен не полностью. Таким образом в методе getInstance будет пропущен синхронизированный блок и будет возвращена ссылка на частично сконструированный объект.

Потокобезопасным способом реализации паттерна Singleton без синхронизации является вариант предложенный Би