public class Singleton
{
private static Singleton _Singleton;
private Singleton(){}
public static Singleton GetInstance() {
if (_Singleton = null)
_Singleton = new Singleton();
return _Singleton;
}
}
생성자가 private으로 외부에서는 인스턴스를 생성하지 못하게 하였고..static으로 구성된 메서드에서
인스턴스를 생성하여 리턴해주는.. 별 문제 없어보이는 방식이다..
위에 소스로 일반적인 방법으로는 문제 없이 잘 돌아간다. 하지만 멀티스레드를 이용하게 될때 문제가 크게 발생하게된다.!!!!!!
GetInstance()메서드가 한번도 실행되지 않은 상태에서.. 두개의 스레드가 동시에 GetInstance()를 호출 하게 된다면..
하나가 아닌 두개의 인스턴스가 생성되어 버리고 말것이다..
2개의 인스턴스를 하나의 인스턴스인줄 알고 사방에서 호출하여 데이타를 주고 받는다면... 엄청난 일이 버러지지 않을까...-_-;
그래서 멀티스레드를 이용하더라도 이러한 문제가 생기지 않도록 할 수 있는 방법을 알아보기로 하자.!
기본적으로 프로그램이 실행되는 순간 인스턴스를 생성!!!
public class Singleton
{
private static Singleton _Singleton = new Singleton();
private Singleton(){}
public static Singleton GetInstance()
{
return _Singleton;
}
}
하지만 위와 같은 방법에도 단점이 있다..
실행되는 순간 바로 인스턴스를 생성하였기 때문에 프로그램을 사용하면서 종료될때까지 한번도 싱글턴으로 이루어진 인스턴스를 호출 하지 않는다면 자원낭비가 될것이다.
물론 무조건 한번은 실행하게 되는 클레스라면 위와같이 구현하더라도 상관없다.
한가지 방법이 더 있다. 바로 Lock을 걸어 사용중이라면 못들어오게 하는 방법이다.
public class Singleton
{
private static Singleton _Singleton;
private Singleton(){}
public static Singleton GetInstance()
{
lock (_Singleton)
{
if (_Singleton == null)
_Singleton = new Singleton();
return _Singleton;
}
}
}
위에 lock로 묶은 부분을 실행할 때에는 _Singleton을 사용하지 못하게 하는 방법이다.
그래서 멀티스레드 방식을 코딩할때에는 lock 키워드를 사용하게 되는 것을 자주 볼 수 있는데...
대신 lock를 걸게되면 시간이 오래 걸린다는 단점이 생긴다. 그래서 lock을 거는 부분을 최소화 시켜주어야 되겠다..
public class Singleton
{
private static Singleton _Singleton;
private Singleton(){}
public static Singleton GetInstance()
{
if (_Singleton == null)
{
lock (_Singleton)
{
_Singleton = new Singleton();
}
}
return _Singleton;
}
}
이번엔 _Singleton == null 일 경우에만 lock을 걸어 보았다. 이렇게 되면 맨 처음 인스턴스를 생성할 때에만 lock을 걸어주게 되어
이후 인스턴스를 불러와서 사용하는 경우에는 아무런 속도저하 없이 사용할 수 있을 것이다.
[출처] [C#]Singleton(싱글턴 패턴)|작성자 깡아