2014-11-06 14 views
7

Mam wielowątkowych aplikacji i singleton Klasa:Threadsafe Singleton bez synchronizacji w Javie?

public final class Singleton { 

    private static MyClass mc; 

    public static final Object getInstance() { 
      if(mc == null) { 
       mc = new MyClass(); 
      } 
      return mc; 
    } 

} 

Oczywiście, to nie będzie działać w ogólnym wielowątkowym scenariuszu. Ale rozważmy następujący scenariusz:

  • Na początku jest tylko jedna nitka
  • nazywa ten jeden wątek getInstance() po raz pierwszy tak że MC jest inicjowany.
  • Po wszystkie inne wątki są uruchamiane przez pierwszy wątek.

Moje założenie:

To powinno działać, ponieważ inicjalizacji pola mc i konstrukcji obiektu zdarzyć, zanim wszystkie kolejne Thread.start() połączeń, które uruchamiają inne wątki. I stanie się Thread.start() dla wątku - przed wszystkimi innymi działaniami tego wątku. Wynika z tego, że inicjalizacja mc ma miejsce - przed wszystkimi działaniami we wszystkich pozostałych wątkach, aby getInstance() zwrócił prawidłową wartość dla wszystkich wątków.

Czy to założenie jest prawidłowe? Dlaczego? Dlaczego nie?

+0

Cóż, @StephenC, lub POWINIENEM spytać ludzi, którzy (miejmy nadzieję) zrozumieją JMM, a tym samym WYZNACZĄ je mnie. – MinecraftShamrock

+0

Wszystko będzie dobrze. Nazywa się "chętną inicjalizacją" (w zasadzie, chociaż twoja forma jest trochę inna, to w końcu to, co robisz). Wygoogluj to. Zobacz także http://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-with-examples#eager-initialization –

+0

Tak, działa, ale jest bardzo delikatny, jak możesz sobie wyobrazić. A koszt robienia tego dobrze, pod względem wydajności, jest znikomy. – assylias

Odpowiedz

5

Twoja analiza jest naprawdę doskonała.

Mówiąc dokładniej: wszystko, co dzieje się w jednym wątku, sekwencyjnie, ma miejsce przedtem (oczywiście, mówi to w ten sposób: "Jeśli x i y są czynnością tego samego wątku, a x pojawia się przed y w porządku programu, to hb (x, y) „)

17.4.5 z JLS potem idzie na powiedzieć, co następuje:

”. wywołanie start() w wątku, dzieje się, przed jakimikolwiek działaniami w uruchomionym wątku . "

Tak więc razem dzieje się jasne, przed zamówieniem między instancją singleton i rozpoczętymi wątkami, dzięki czemu mają zagwarantowaną aktualną wartość.

Po prostu: Utworzony wątek gwarantuje, że wszystko, co zrobił rodzic, zostało utworzone przed jego utworzeniem, w przeciwnym razie programowanie współbieżne byłoby prawie niemożliwe.

+0

Mogę potwierdzić, że @Voo jest w 100% poprawne. Robię to już od ponad dekady bez żadnych problemów. – edharned

+0

Dziękuję za szczegółową odpowiedź :) – MinecraftShamrock

+0

@StephenC Rozumowanie opiera się na regułach JMM o zdarzeniach przed relacjami i kiedy istnieją między dwoma akcjami. Jakie byłoby Pana zdaniem lepsze uzasadnienie? – MinecraftShamrock