2011-11-30 4 views
1

나는 아래와 같이 싱글 톤 클래스를 구현 한 :멀티 스레드 환경에서 싱글 톤 패턴과 관련된 문제가 있습니까?

public class Singleton { 

    private static Singleton instance = null; 


    private Singleton() { 
    } 

private synchronized static void createInstance() { 
    instance = new Singletone(); 
} 


    public static Singleton getInstance() { 
     if(instance == null){ 
      createInstance(); 
     } 
     return instance; 
    } 

} 

그러나 나는 그것이 싱글 톤의 올바른 구현 있는지 알고 싶습니다. 다중 스레드 환경에 문제가 있습니까?

+0

오타 : Singletone이 아닌 _Singleton_입니다. 그리고 네, 이것은 쓰레드 안전 싱글 톤이 아닙니다. – zengr

+1

가능한 [자바 싱글 톤 스레드 안전] (http://stackoverflow.com/questions/4965534/java-singleton-thread-safe) – zengr

+1

가능한 중복 : http://stackoverflow.com/questions/70689/efficient-way -to-implement-singleton-pattern-in-java –

답변

5

귀하의 구현이 거의 정확합니다. 문제는 스레드로부터 안전하지 않다는 것입니다. 2 개의 개별 쓰레드는 getInstance()을 동시에 입력 할 수 있습니다. 인스턴스가 null인지 확인한 다음 클래스의 인스턴스를 2 개 생성하십시오. 수정 사항은 다음과 같습니다.

public static synchronized Singletone getInstance() { 
    if(instance == null){ 
     createInstance(); 
    } 
    return instance; 
} 

synchronized에주의하십시오.

0

실제로는 createInstance 메서드가 필요하지 않지만 이것은 싱글 톤 패턴의 올바른 구현입니다. 당신은 getInstance에서 이것을 인라인 할 수 있습니다. 또한 "Singleton"이라는 철자로 끝나며 "e"가 없습니다.

가끔씩 다중 스레드 환경에서 문제를 만들 수 있습니다. 두 개의 프레임 포인터가 동시에 getInstance를 입력하면 처음 입력 한 프레임은 Singleton의 인스턴스를 가져올 수 있고 두 번째 프레임 포인터는 다른 인스턴스를 가져옵니다.

이것은 사용 방법에 따라 다릅니다. 스레드를 설정하기 전에 싱글 톤을 사용하면 문제가 없습니다. 이것이 우려된다면 먼저 싱글 톤을 초기화하는 것을 고려할 수 있습니다. 메서드 선언에 synchronized 키워드를 사용하여이 문제를 해결할 수도 있습니다.

7
public enum Singleton { 
    INSTANCE; 
    private int val; 

    public int getVal() { 
     return val; 
    } 
} 

사용법 :

Singleton.INSTANCE.getVal(); 

이것은 당신이 열거 지원을 자바 버전> 5.0에 대한 완벽한 싱글이다.

Joshua Bloch의 Effective Java에서도 언급되었습니다. 여기에 관한 블로그 게시물 : Enum Singleton

업데이트 : 또한
, 싱글 톤을 사용하십시오 100 % 경우에만 당신이 하나 필요 해요! 그것은 코드의 테스트 가능성을 죽입니다! 그러나 당신은 공장에서 말하면 그것을 피할 수 없습니다.
하지만 악용하지 마시고, 실제로 필요한 곳에 사용하십시오. 그것의 사용을 이해하십시오.

+0

@Downvoter : 설명하자면? – zengr

+1

죄송합니다. 우발적으로 다운볼트되었습니다.이 사실을 명확히 할 수 없으므로이 +1이 차선책입니다. –

-1

구현이 잘된 것처럼 보입니다. 단일 JVM에서 멀티 스레딩은 그러한 종류의 싱글 톤 문제에 대해서는 문제가되지 않지만 클러스터 된 (두 개 이상의 JVM)에서 문제를 일으킬 수 있습니다.

이러한 문제가 계속되는 경우 http://java.sun.com/developer/technicalArticles/Programming/singletons/을 참조하십시오.

아, 싱글 톤이 아니라 싱글 톤입니다. :)

+2

실제로 ** 단일 JVM에서도 ** 멀티 스레드 문제 일 수 있습니다. 귀하의 링크는 또한 "잘못된 동기화로 인한 다중 인스턴스"에서이 문제를 다루고 있습니다. – Boris

0

싱글 톤은 스레드로부터 안전하지 않습니다. 이러한 이유 때문에 Double-checked Locking이 소개되었습니다.

Java SE 5 이상에서는 volatile 정적 인스턴스를 사용할 수 있습니다. Java VM에서는, 복수의 thread가 실행될 때, 올바르게 싱글 톤을 처리하는 방법을 인식합니다.

자세한 내용은 Double-checked locking.

+0

포함 된 링크에서 : "이 기술은 많은 미묘한 문제가있어서 일반적으로 피해야합니다" –

0

지연 초기화 구현의 경우, 스레드 안전을 위해 getInstance() 메소드를 동기화해야합니다.

public static synchronized Singleton getInstance() 

또는 이미 스레드 세이프 인 클래스 로딩 시간에 간단히 초기화 할 수 있습니다.

private static Singleton instance = new MySingleton(); 
2

위의 열거 형 이외의 다른 최적의 메커니즘은 정적 초기화라고합니다. 이를 통해 Java 메모리 모델의 보장에 의존하게되므로 항상 작동하도록 보장됩니다. 다음은이 방법을 보여줍니다 an answer to a different question에서 단편이다 :

class Singleton { 
    static class SingletonHolder { 
     static final Singleton INSTANCE = new Singleton(); 
    } 
    public static Singleton instance() { 
     return SingletonHolder.INSTANCE; 
    } 
} 

Singleton 인스턴스가있는 SingletonHolder 클래스 객체는 SingletonHolder.INSTANCE가 호출되어 처음 만들어집니다.

Java 메모리 모델은 정적 코드 (new Singleton())가 하나의 스레드에서만 실행되도록 보장합니다. 따라서 이중 잠금 검사 (작동하지 않음) 및 불필요한 동기화가 필요하지 않습니다. 이후의 모든 호출은 그 하나의 인스턴스를 가져옵니다.

관련 문제