스레드 안전 C # 싱글 톤 패턴
http://msdn.microsoft.com/en-us/library/ff650316.aspx에 설명 된 싱글 톤 패턴에 대한 몇 가지 질문이 있습니다.
다음 코드는 기사에서 발췌 한 것입니다.
using System;
public sealed class Singleton
{
private static volatile Singleton instance;
private static object syncRoot = new object();
private Singleton() {}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}
특히, 위의 예에서 잠금 전후에 인스턴스를 null과 두 번 비교할 필요가 있습니까? 이것이 필요합니까? 먼저 잠금을 수행하고 비교해 보는 것은 어떻습니까?
다음을 단순화하는 데 문제가 있습니까?
public static Singleton Instance
{
get
{
lock (syncRoot)
{
if (instance == null)
instance = new Singleton();
}
return instance;
}
}
잠금을 수행하는 데 비용이 많이 듭니까?
잠금을 수행하는 것은 단순한 포인터 검사와 비교할 때 엄청나게 비쌉니다 instance != null.
여기에 표시되는 패턴을 이중 확인 잠금 이라고 합니다. 그 목적은 한 번만 필요로하는 값 비싼 잠금 작업을 피하는 것입니다 (싱글 톤이 처음 액세스 될 때). 구현은 싱글 톤이 초기화 될 때 스레드 경쟁 조건으로 인한 버그가 없는지 확인해야하기 때문에 그러한 것입니다.
다음과 같이 생각해보십시오. 맨 null체크 (가없는 lock)는 해당 대답이 "예, 객체가 이미 생성되었습니다"일 때만 올바른 사용 가능한 대답을 제공하도록 보장됩니다. 그러나 대답이 "아직 구성되지 않음"이면 충분한 정보가없는 것입니다. "아직 구성되지 않았고 다른 스레드가 곧 구성 할 의도 가 없다는 것"을 알고 싶었 기 때문 입니다. 따라서 외부 검사를 매우 빠른 초기 테스트로 사용하고 답이 "아니오"인 경우에만 적절하고 버그가 없지만 "비싼"절차 (잠금 후 검사)를 시작합니다.
위의 구현은 대부분의 경우에 충분하지만이 시점 에서 다른 대안도 평가하는 C #의 싱글 톤에 대한 Jon Skeet의 기사를 읽어 보는 것이 좋습니다 .
게으른 버전 :
public sealed class Singleton
{
static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton());
private Singleton() { }
public static Singleton Instance => lazy.Value;
}
.NET 4 및 C # 6.0 (VS2015) 이상이 필요합니다.
잠금 수행 : 상당히 저렴합니다 (널 테스트보다 여전히 비쌉니다).
다른 스레드가 잠금을 수행 할 때 잠금 수행 : 잠금을 수행하는 동안 수행해야하는 작업에 대한 비용이 사용자의 시간에 추가됩니다.
다른 스레드에 잠금이 있고 수십 개의 다른 스레드도 대기 중일 때 잠금 수행 : Crippling.
성능상의 이유로 항상 가능한 한 가장 짧은 시간 동안 다른 스레드가 원하는 잠금을 갖고 싶어합니다.
물론 좁은 것보다 "넓은"자물쇠에 대해 추론하는 것이 더 쉽기 때문에 넓게 시작하여 필요에 따라 최적화하는 것이 가치가 있지만, 좁은 것이 패턴에 맞는 경험과 친숙 함으로부터 배운 경우가 있습니다.
(부수적으로, 그냥 사용할 수 private static volatile Singleton instance = new Singleton()있거나 싱글 톤을 사용할 수 없지만 대신 정적 클래스를 사용할 수 있다면 둘 다 이러한 문제와 관련하여 더 좋습니다).
그 이유는 성능 때문입니다. instance != null(처음을 제외하고는 항상 그럴 것임) 비용이 많이 드는 경우 lock: 초기화 된 싱글 톤에 동시에 액세스하는 두 개의 스레드가 불필요하게 동기화됩니다.
거의 모든 경우 (즉, 첫 번째 경우를 제외한 모든 경우) instance는 null이 아닙니다. 잠금을 획득하는 것은 간단한 확인보다 비용이 많이 들기 때문에 instance잠금 전의 값을 한 번 확인 하는 것은 훌륭하고 무료 최적화입니다.
이 패턴을 이중 검사 잠금이라고합니다. http://en.wikipedia.org/wiki/Double-checked_locking
Jeffrey Richter는 다음을 권장합니다.
public sealed class Singleton
{
private static readonly Object s_lock = new Object();
private static Singleton instance = null;
private Singleton()
{
}
public static Singleton Instance
{
get
{
if(instance != null) return instance;
Monitor.Enter(s_lock);
Singleton temp = new Singleton();
Interlocked.Exchange(ref instance, temp);
Monitor.Exit(s_lock);
return instance;
}
}
}
@andasa의 게으른 버전을 선호하지만 응용 프로그램 요구 사항에 따라 스레드로부터 안전한 Singleton 인스턴스를 열심히 만들 수 있습니다. 이것은 간결한 코드입니다.
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
private Singleton() { }
public static Singleton Instance()
{
return instance;
}
}
다음 코드 줄이 애플리케이션 시작시 Singleton 인스턴스를 만드는 다른 버전의 Singleton입니다.
private static readonly Singleton singleInstance = new Singleton();
Here CLR (Common Language Runtime) will take care of object initialization and thread safety. That means we will not require to write any code explicitly for handling the thread safety for a multithreaded environment.
"The Eager loading in singleton design pattern is nothing a process in which we need to initialize the singleton object at the time of application start-up rather than on demand and keep it ready in memory to be used in future."
public sealed class Singleton
{
private static int counter = 0;
private Singleton()
{
counter++;
Console.WriteLine("Counter Value " + counter.ToString());
}
private static readonly Singleton singleInstance = new Singleton();
public static Singleton GetInstance
{
get
{
return singleInstance;
}
}
public void PrintDetails(string message)
{
Console.WriteLine(message);
}
}
from main :
static void Main(string[] args)
{
Parallel.Invoke(
() => PrintTeacherDetails(),
() => PrintStudentdetails()
);
Console.ReadLine();
}
private static void PrintTeacherDetails()
{
Singleton fromTeacher = Singleton.GetInstance;
fromTeacher.PrintDetails("From Teacher");
}
private static void PrintStudentdetails()
{
Singleton fromStudent = Singleton.GetInstance;
fromStudent.PrintDetails("From Student");
}
This is called Double checked locking mechanism, first, we will check whether the instance is created or not. If not then only we will synchronize the method and create the instance. It will drastically improve the performance of the application. Performing lock is heavy. So to avoid the lock first we need to check the null value. This is also thread safe and it is the best way to achieve the best performance. Please have a look at the following code.
public sealed class Singleton
{
private static readonly object Instancelock = new object();
private Singleton()
{
}
private static Singleton instance = null;
public static Singleton GetInstance
{
get
{
if (instance == null)
{
lock (Instancelock)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
}
참고URL : https://stackoverflow.com/questions/12316406/thread-safe-c-sharp-singleton-pattern
'Program Club' 카테고리의 다른 글
| asp.net에서 영구 쿠키를 만드는 방법은 무엇입니까? (0) | 2020.11.03 |
|---|---|
| 어댑터로 목록보기를 동적으로 업데이트 (0) | 2020.11.03 |
| 로컬 저장소에서 업스트림을 제거하는 힘내 (0) | 2020.11.03 |
| Flask에서 매시간 실행되도록 함수 예약 (0) | 2020.11.03 |
| 사실 테이블과 차원 테이블의 차이점은 무엇입니까? (0) | 2020.11.02 |