Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Синхронизация синглетона / 25 сообщений из 36, страница 1 из 2
26.05.2006, 11:23
    #33753539
unicornmirage
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
Добрый день всем участникам форума!

позвольте задать такой вопрос:
У меня есть класс построенный по шаблону Singleton. Экземпляр этого класса используется в мультипоточном контексте (сервлетами). Для создания экземпляра класса использую фабрику:

Код:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
class MySingleton {
        private static MySingleton oneInst;

        private  MySingleton () {} 

        /**
         * данный метод я синхронизирую чтобы изключить возможность множественных вызов
         * из разных потоков
         */
        public static synchronized  MySingleton getInstance () {
                if(oneInst == null) {
                        oneInst = new  MySingleton ();
                }
                return oneInst ;
        }
}


Так как экземпляр класса MySingleton используется очень часто, разумеется мне не понравилось что при получении ссылки на него приходится вызывать синхронизированный метод getInstance. Тогда я сделал вторую фабрику:

Код:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
class MegaFactory {
        private static MySingleton oneInst;

       public static  MySingleton getMySingleton() {
              if (oneInst == null) {
                      oneInst = MySingleton.getInstance();  // синхронизация используется один раз
              }
              return  oneInst;
       }
}


у фабрики MegaFactory есть метод getMySingleton который не синхронизирован, тем не менее синхрнонизация используется внутри него при условии если объект класса MySingleton не создан.

Потом у меня возникла идея отказаться от этой фабрики и сделать таким образом:
Код:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
class MySingleton {
        private static MySingleton oneInst = new MySingleton ();

        private  MySingleton () {} 

        /**
         * данный метод уже не синхронизирован
         */
        public static MySingleton getInstance () {
                return oneInst ;
        }
}


Скажите пожалуйста, правильно ли я сдеал? Какой из этих вариантов лучший? Или синхронизация не нужна вообще в этой задаче?
Спасибо за внимание!
...
Рейтинг: 0 / 0
26.05.2006, 11:24
    #33753546
unicornmirage
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
извините, теги оказывается другие тут...

У меня есть класс построенный по шаблону Singleton. Экземпляр этого класса используется в мультипоточном контексте (сервлетами). Для создания экземпляра класса использую фабрику:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
class MySingleton {
private static MySingleton oneInst;

private MySingleton () {}

/**
* данный метод я синхронизирую чтобы изключить возможность множественных вызов
* из разных потоков
*/
public static synchronized MySingleton getInstance () {
if(oneInst == null) {
oneInst = new MySingleton ();
}
return oneInst ;
}
}

Так как экземпляр класса MySingleton используется очень часто, разумеется мне не понравилось что при получении ссылки на него приходится вызывать синхронизированный метод getInstance. Тогда я сделал вторую фабрику:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
class MegaFactory {
private static MySingleton oneInst;

public static MySingleton getMySingleton() {
if (oneInst == null) {
oneInst = MySingleton.getInstance(); // синхронизация используется один раз
}
return oneInst;
}
}

у фабрики MegaFactory есть метод getMySingleton который не синхронизирован, тем не менее синхрнонизация используется внутри него при условии если объект класса MySingleton не создан.

Потом у меня возникла идея отказаться от этой фабрики и сделать таким образом:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
class MySingleton {
private static MySingleton oneInst = new MySingleton ();

private MySingleton () {}

/**
* данный метод уже не синхронизирован
*/
public static MySingleton getInstance () {
return oneInst ;
}
}

Скажите пожалуйста, правильно ли я сдеал? Какой из этих вариантов лучший? Или синхронизация не нужна вообще в этой задаче?
Спасибо за внимание!
...
Рейтинг: 0 / 0
26.05.2006, 12:24
    #33753813
ponomarevvb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
По-моему, в последнем варианте всё равно надо синхронизировать метод.
--С уважением, ponomarevvb--
...
Рейтинг: 0 / 0
26.05.2006, 14:29
    #33754401
OU
OU
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
2 unicornmirage:
В первом случае все правильно, код должен быть synchronized. Второй вариант не имеет смысл (с точки зрения того для чего вы его писали), так как метод getMySingleton() все равно вызывает внутри себя synchronized метод getInstance(). Третий вариант правильный.

Первый вариант хуже третьего в производительности (так как поток должен все равно выполнить проверку условия), но лучше в обслуживании (можно обрабатывать исключения).
Третий вариант лучше первого в производительности, но хуже в обслуживании (данный метод инициализации не позволяет обрабатывать исключения).
...
Рейтинг: 0 / 0
26.05.2006, 14:47
    #33754462
unicornmirage
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
OU.
Третий вариант лучше первого в производительности, но хуже в обслуживании (данный метод инициализации не позволяет обрабатывать исключения).

а какие здесь могут возникнуть исключения? конфликт доступа?
...
Рейтинг: 0 / 0
26.05.2006, 15:38
    #33754654
OU
OU
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html
...
Рейтинг: 0 / 0
26.05.2006, 16:39
    #33754899
Jozic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
а так?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
     public   static  MySingleton getInstance() {
         if  ( oneInst ==  null  ) {
             synchronized  ( MySingleton. class  ) {
                 if  ( oneInst ==  null  ) {
                    oneInst =  new  MySingleton();
                }
            }
        }
         return  oneInst;
    }
...
Рейтинг: 0 / 0
26.05.2006, 17:24
    #33755098
SqlLoader
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
Jozicа так?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
     public   static  MySingleton getInstance() {
         if  ( oneInst ==  null  ) {
             synchronized  ( MySingleton. class  ) {
                 if  ( oneInst ==  null  ) {
                    oneInst =  new  MySingleton();
                }
            }
        }
         return  oneInst;
    }


Так нельзя. Читай про Double-checked locking.
...
Рейтинг: 0 / 0
26.05.2006, 18:59
    #33755361
Jozic
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
SqlLoaderТак нельзя. Читай про Double-checked locking.спасибо :)
http://www-128.ibm.com/developerworks/java/library/j-dcl.html
...
Рейтинг: 0 / 0
27.05.2006, 04:06
    #33755717
Кувалдин Роман
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
Мистер Блох советует делать это вот так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
 public   class  FooSingleton
{
     private  FooSingleton()
    {
        // тело конструктора
    }

     private   static   class  FooHolder
    {
         static   final  FooSingleton instance =  new  FooSingleton();
    }

     public   static  FooSingleton getInstance()
    {
         return  FooHolder.instance;
    }

Joshua BlochThe idiom takes advantage of the guarantee that a class will not be initialized until it is used [JLS, 12.4.1]. When the getFoo method is invoked for the first time, it reads the field FooHolder.foo, causing the FooHolder class to get initialized. The beauty of this idiom is that the getFoo method is not synchronized and performs only a field access, so lazy initialization adds practically nothing to the cost of access. The only shortcoming of the idiom is that it does not work for instance fields, only for static fields.


======================
- Я подхожу к клетке с медведем панда...
Видите, какие у него черные круги под глазами?!
Медведь панда как бы всем своим видом говорит нам: "Не бухайте!"
======================
...
Рейтинг: 0 / 0
27.05.2006, 14:58
    #33755945
OU
OU
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
2 Роман:
По видимому код не полный, т.к он не совсем подходит под приведенное описание. В частности нет members getFoo и foo. Если не затруднит то не могли бы вы привести ссылку на оригинал.
...
Рейтинг: 0 / 0
27.05.2006, 15:09
    #33755953
Кувалдин Роман
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
OU2 Роман:
По видимому код не полный, т.к он не совсем подходит под приведенное описание. В частности нет members getFoo и foo. Если не затруднит то не могли бы вы привести ссылку на оригинал.

foo = instance;
getFoo = getInstance;

Извини, бездумно скопировал текст с Блоха, а исходники чуточку переименовал.

Саму книгу можно скачать из библиотеки уважаемого Грасоff-а:

http://lib.swapj.net/books/effective-java-programming-language-guide.zip

Глава 9, задача 48.
...
Рейтинг: 0 / 0
27.05.2006, 15:34
    #33755979
OU
OU
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
2 Роман:

спасибо, пойду гляну
...
Рейтинг: 0 / 0
27.05.2006, 23:30
    #33756391
softwarer
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
Кувалдин РоманМистер Блох советует делать это вот так:
Решение изящное, но возможно по невежеству возникают два вопроса. Нельзя ли коротко прояснить их?

1. Зачем делать внутренний класс? Статический член того же класса, по идее, должен сработать не хуже, инициализируясь при первом использовании класса, то есть в большинстве случаев - при первом вызове getInstance().

2. А дает ли это реальный выигрыш, учитывая, что где-нибудь внутри неявно вызванного getClass() будет та же самая синхронизация?
...
Рейтинг: 0 / 0
28.05.2006, 19:09
    #33756934
Кувалдин Роман
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
softwarer Кувалдин РоманМистер Блох советует делать это вот так:
Решение изящное, но возможно по невежеству возникают два вопроса. Нельзя ли коротко прояснить их?

1. Зачем делать внутренний класс? Статический член того же класса, по идее, должен сработать не хуже, инициализируясь при первом использовании класса, то есть в большинстве случаев - при первом вызове getInstance().

2. А дает ли это реальный выигрыш, учитывая, что где-нибудь внутри неявно вызванного getClass() будет та же самая синхронизация?

Не знаю, но поскольку Блох один из разработчиков языка - склонен ему верить. Желания ковыряться в исходниках JRE у меня нет :-)
...
Рейтинг: 0 / 0
22.06.2006, 13:45
    #33808629
MalkoLinge
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
ublic  class  SigletonFactory {
	 private   static  Object object;
	 static  {
		 synchronized  (object) {
			object =  new  Object();

		}
	}	
	 private  SigletonFactory() {	}
	 public  Object getInstance(){
		 return  object;
	}
	

}
...
Рейтинг: 0 / 0
22.06.2006, 13:47
    #33808644
MalkoLinge
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
Syncronized там просто потому что я не очень крутой джавист и не уверен до конца, что статическая секция может быть выполнена несколько раз из разныхпотоков. но уверен что оно там не нужно
WBR,
Malkolinge
...
Рейтинг: 0 / 0
22.06.2006, 13:48
    #33808655
MalkoLinge
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
окончательній вариант
Код: plaintext
1.
2.
 public   static  Object getInstance(){
		 return  object;
	}
WBR,
Malkolinge
...
Рейтинг: 0 / 0
22.06.2006, 14:18
    #33808780
BlackWall
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
1. Синхронизация на неинициализированный член object приводит к NullPointerException.
2. Блох хотел сказать, что пока не вызван метод getInstance() класса FooSingleton, экземпляр этого класса создан не будет. Вызов метода getInstance() приведет к инициализации статических членов класса FooHolder, в частности instance. В результате будет создан экземпляр класса FooSingleton.В принципе, такой вариант эквивалентен варианту 1 первого поста, но порождает еще один класс.
...
Рейтинг: 0 / 0
01.08.2006, 23:36
    #33893237
ska
ska
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
SqlLoader Jozicа так?
...


Так нельзя. Читай про Double-checked locking.

Зато так всегда работало.

для C#
или в java
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
 public   class  Single
{
	 private   static  Single instance =  null ;
	 private  Single() {
		// do initiation
	}
	
	 public   static  Single getSingle()
	{
		 if  (instance !=  null )  return  instance;
		 synchronized  (Single. class ) {
			 if  (instance !=  null )  return  instance;
			Single a =  new  Single();
			 synchronized  (a) {
				instance = a;
				 return  instance;
			}
		}
	}
}

есть сомнения ?
...
Рейтинг: 0 / 0
01.08.2006, 23:59
    #33893250
Кувалдин Роман
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
ska...есть сомнения?...

Есть
...
Рейтинг: 0 / 0
02.08.2006, 00:07
    #33893255
Кувалдин Роман
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
Извиняюсь, сразу не вкурил в вышеописанную муть. Да, так наверное будет работать. Но во первых вложенная синхронизация, а во вторых дополнительный объект мне очень не нравятся.

======================
- Я подхожу к клетке с медведем панда...
Видите, какие у него черные круги под глазами?!
Медведь панда как бы всем своим видом говорит нам: "Не бухайте!"
======================
...
Рейтинг: 0 / 0
02.08.2006, 00:18
    #33893263
ska
ska
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
Кувалдин Роман ska...есть сомнения?...

Есть

А зря :-))
В статеечке конечно всё верно, и про volatile в том числе (а были ссылочки на еще одну аналогичную статейку от IBM), но беда этих статей в том что все они говорят как нельзя, но не упоминают (или мало и нежизненно) как можно.

Если Вам удастся показать (хотя бы предположить теоретически) где в моём примере может быть прокол (можно с кодами из разных JIT - x86, x64, pa-risc, power, sparc, ia64) - сниму шляпу.
А вообще идея в том что "synchronized(a)" нельзя обойти или соптимизировать.

Я конечно не беру 1.1.7 Symantec JIT который еще не соблюдал правила по synchronized.

Сергей
...
Рейтинг: 0 / 0
02.08.2006, 00:23
    #33893264
ska
ska
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
Кувалдин РоманИзвиняюсь, сразу не вкурил в вышеописанную муть. Да, так наверное будет работать. Но во первых вложенная синхронизация, а во вторых дополнительный объект мне очень не нравятся.

Так вот как раз без этой вложенной синхронизации (и не по тому же самому обьекту) и нарываемся на проблемы. Черт с ней - ведь это только 1 раз, зато все остальные вызовы пойдут без синхронизации.
...
Рейтинг: 0 / 0
02.08.2006, 10:50
    #33893805
funikovyuri
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Синхронизация синглетона
unicornmirage
ваш второй вариант верен и обычно называется двойное проверкой. метод новый делать не обязательно, достаточно написать
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
 class  MySingleton {
 private   static  MySingleton oneInst =  null ;

 public   static  getInstance() {
   if  (oneInst== null ) {
     synchronized  ( this ) {
           if  (oneInst== null )
             oneInst =  new  MySingleton();
    }

  }

     return  oneInst;
  }
}
вообще решение классическое

насчет вашего третьего примера, он рабочий только инициализация экземпляра синглтона будет происходить не в момент первого обращения, а при загрузке класса.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Синхронизация синглетона / 25 сообщений из 36, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]