1

나는 달성하려고하는 것에 대해 한 시간 동안 집중을 찾고 있지만 특정한 방향으로 결정적인 것을 찾지 못했다. 다음과 같이로딩이 실패 할 때 쓰레드 세이프 (Threadsafe) 게으른 로딩

내 상황은 다음과 같습니다

  • 내가 (.NET 웹 서비스) 나는로드 무시할 수없는 시간을 개체를 사용하여 수업을
  • 다중 스레드 응용 프로그램을 가지고, 그래서 나는 것

내가 이전에이를 구성 접근 방식을 사용했다 정적 클래스 멤버

  • 간헐적으로 이러한 개체를 구성 실패의 낮은 기회가 코드로 유지하고자 정적 생성자의 객체. 이 문제는 위에서 언급 한 것처럼 생성자가 때때로 실패하고 .NET 정적 생성자가 실패하면 전체 클래스가 프로세스가 다시 시작될 때까지 닫힙니다. 이 접근 방식에는 두 번째 기회가 없습니다.

    가장 직관적으로 보이는 접근법은 이중 확인 잠금을 사용하는 것입니다. 그 두 번 체크 잠금의 악마에 대해 얘기하고 주위에 페이지가 많이 있는데, 내가 이미하고있는 정적 생성자를 사용하는 말,하지만 그것은 나를 위해 옵션이 될 것하지 않는 정적 생성자가 실패하고 전체 수업을 중단시킬 잠재력.

    구현 (단순화 된, 당연히) 나는 다음을 사용하려고 생각합니다. 모든 클래스와 멤버 이름은 순수하게 설명하는 것이며 실제로 사용하는 이름이 아닙니다. 이 접근법은 문제가 될 것입니까? 누구든지 더 나은 접근법을 제안 할 수 있습니까? 당신이 .NET 4.0을 사용하는 경우

    public class LazyMembers 
    { 
        private static volatile XmlDocument s_doc; 
        private static volatile XmlNamespaceManager s_nsmgr; 
        private static readonly object s_lock = new object(); 
    
        private static void EnsureStaticMembers() 
        { 
         if (s_doc == null || s_nsmgr == null) 
         { 
          lock (s_lock) 
          { 
           if (s_doc == null || s_nsmgr == null) 
           { 
            // The following method might fail 
            // with an exception, but if it succeeds, 
            // s_doc and s_nsmgr will be initialized 
            s_doc = LoadDoc(out s_nsmgr); 
           } 
          } 
         } 
        } 
    
        public XmlNamespaceManager NamespaceManager 
        { 
         get 
         { 
          EnsureStaticMembers(); 
          return s_nsmgr; 
         } 
        } 
    
        public XmlDocument GetDocClone() 
        { 
         EnsureStaticMembers(); 
         return (XmlDocument)s_doc.Clone(); 
        } 
    } 
    
  • +0

    .NET에서 이중 확인 잠금 기능이 작동하지 않습니까? 소환? –

    +0

    Jon Skeets의 기사가 가장 눈에 띄었지만 C#에서 안전한지 아무도 모르는 것을 말하는 많은 기사와 포럼 스레드를 보았습니다. 그리고/또는 전체적으로 사용하지 말 것을 권장했습니다. 아직 .NET에서 사용하는 사람을 실제로 추천합니다. – Jimmy

    +1

    나는 Jon이 매우보기 흉한 분석을했다고 생각한다. 그것은 작동하지만 "플랫폼 버전"과 함께 "메모리 모델"과 같은 단어는 당신을 놀라게 할 것입니다. 휘발성을 사용하여 –

    답변

    2

    당신이 Lazy<T>LazyThreadSafetyMode를 참조 할 수 있습니다 (당신이 T의 몇 가지 인스턴스가 다중 스레드 환경에서 만든 여부를할지 여부에 따라 달라집니다. 귀하의 경우에는 당신이 Lazy<T>(Func<T> func, LazyThreadSafetyMode를 참조해야) 생성자 - here(MSDN)

    그렇지 않으면 (3.5 이하를 사용하는 경우) CAS techinque를 사용하여 잠금없이 단일 인스턴스를 만들 수 있습니다. 이 같은

    뭔가 :

    get { 
        if(_instance == null) { 
         var singleton = new Singleton(); 
         if(Interlocked.CompareExchange(ref _instance, singleton, null) != null) { 
          if (singleton is IDisposable) singleton.Dispose(); 
         } 
        } 
        return _instance; 
    } 
    

    그러나, 여기 만 LazyThreadSafetyMode.Publications 동작을 얻을 수 있습니다 - 단 하나 개의 인스턴스가 다른 스레드를 볼 수 있지만, 몇 만들 수 있습니다.

    또한 코드에서 null을 두 번 확인하면 아무런 문제가 없어야합니다. .NET 환경에서는 안전합니다 (최소한 x86 컴퓨터 및 관련 메모리 모델에서는). 2004 년 이전에는 자바 세계에서 몇 가지 문제가있었습니다. AFAIK.

    +0

    입력 해 주셔서 감사합니다. lock() 접근법은 두 개의 변수로 초기화 작업을하기 때문에 더 간단하고 더 적합 해 보입니다. 그러나 앞으로의 문제에 대해서는 Interlocked.CompareExchange()를 사용하는 것이 좋습니다. .NET 4를 사용하고 있지 않습니다.0이므로 Lazy 은 현재 옵션이 아닙니다. – Jimmy

    관련 문제