2009-10-26 3 views
1

내 웹 응용 프로그램에 필요한 DB 연결과 유사한 객체가 있습니다. 그것은 매우 느리게 만들어지며 거의 사용되지 않을 것입니다. 그래서 나는 그것의 인스턴스를 하나만 유지하고 싶습니다. 여러 요청이 동시에 그것을 필요로한다면, 그들은 객체를 lock()하고 그들의 접근을 직렬화 할 것이다.IDisposable의 스레드로부터 안전한 단일 인스턴스를 만드는 방법은 무엇입니까?

더 재미있게 만들기 위해 개체는 IDisposable이며 닫을 수 있습니다. 당연히, 나는 그것을 닫는 코드를 쓰는 것을 피할 것이지만 ... 알다시피 ... 미안보다 더 안전하다, 그렇지?

그래서 순진한 접근 방식이이 같은 것을 구현하는 것입니다 :

private static DBClass _Instance; 
private static object _DBLock = new object(); 

public DBClass GetDB() 
{ 
    if (_Instance == null) 
     lock (_DBLock) 
      if (_Instance == null) 
       _Instance = CreateInstance(); 
    lock (_Instance) 
     if (_Instance.Disposed) 
      _Instance = CreateInstance(); 
    return _Instance; 
} 

은 다음과 같이 사용됩니다 :

lock (var Conn = Global.GetDB()) 
{ 
    // Use Conn here. 
} 

이 아마 대부분의 시간을 작동합니다,하지만 난 악용 될 수있는 개통을보십시오. 두 개의 스레드가 동시에 이것을 호출하면 동일한 인스턴스를 동시에 얻은 다음 다른 스레드가 lock()을 얻기 전에 여전히 Dispose() 일 수 있습니다. 따라서 - 나중에 코드가 실패합니다. 그것을 사용하는 모든 장소에서 Disposed을 확인하는 것은 또한 어색해 보입니다. 실제로, lock()은 너무 어색해 보이지만 인스턴스는 본질적으로 쓰레드 안전하지 않으므로 그것에 대해 할 수있는 일은 없습니다.

어떻게 구현하나요?

답변

2

처음에는 이중 잠금을 피하는 것이 좋습니다. 변수를 가변적으로 만들어서는 안됩니다.이 경우처럼 잘못 입력하는 것은 매우 쉽습니다.

실제로는 개체를 처분하고 싶지 않은 경우 동일한 API를 구현하지만 처분이 노출되지 않는 이유가 무엇입니까? 이렇게하면 실제로 객체를 사용하는 방법에 따라 잠재적으로 잠금을 캡슐화 할 수도 있습니다. 이 작업을 수행하는 또 다른 방법은 API를 Action<DBClass>으로 노출하는 것입니다. 객체로 수행하려는 작업을 전달하면 도우미가 인스턴스를 만들고 적절하게 잠금 처리합니다.

최종 점 하나 :이 모든 것은 테스트 가능성 측면에서 다소 까다 롭습니다. 당신이 단위 테스트 등의 팬인지는 모르겠지만, 싱글 톤은 종종 테스트를 위해 다소 어색한 삶을 만듭니다.

+0

이 문제는이 객체에 대한 참조를 보유하고 그 객체에 대한 연산을 수행하는 다른 객체를 반환한다는 점에서 문제가 있습니다. 몇 백 권의 수업을 끝내지 않는다면 효과가 없을 것입니다. Action <> 접근법은 주목할 만하다.하지만 코드의 증가 된 혼란이 그만한 가치가 있는지 궁금하다. 나는 우아한 접근 방식을 원하지만, 이것은 다른 방향으로가는 것입니다 ... –

+0

Btw - 어쨌든 락()을 사용하고 있습니다. 왜 휘발성에 대한 필요성? –

+1

* 보조 * 잠금으로 인해 실제로는 괜찮을 수도 있습니다. 그러나 두 개의 다른 잠금 장치가 포함되어 있다고 가정 할 때 진정으로 * 괜찮은지는 분명하지 않습니다. 나는 개인적으로 모든 것을 위해 하나의 잠금을 사용할 것입니다. - 전체 메소드를'_DBLock'을 사용하는 lock 문에 넣으십시오. 메모리 모델의 미묘함은 꽤 까다 롭습니다. 마찬가지로 다른 스레드가 * locking을 사용하지 않고 * 폐기하는 객체를 사용하는 경우이를 발견하고 새 인스턴스를 만들지는 보장 할 수 없습니다. 기본적으로이 디자인이 많은 미묘한 버그를위한 여지를 여는 것처럼 느껴집니다. –

관련 문제