2013-03-01 2 views
-1

아래 코드와 같이 'LogLevels'라는 공용 속성이있는 정적 클래스 'Logger'가 있습니다.동시에 사용될 때 정적 클래스의 정적 속성

다중 사용자 또는 멀티 스레드 환경에서 동시에 속성을 사용하면이 문제를 일으킬 수 있습니까?

'LogLevels'속성의 코드에 스레드 동기화을 사용해야합니까?

public class Logger 
{ 
    private static List<LogLevel> _logLevels = null; 


    public static List<LogLevel> LogLevels 
    { 
     get 
     { 
      if (_logLevels == null) 
      { 
       _logLevels = new List<LogLevel>(); 
       if (!string.IsNullOrWhiteSpace(System.Configuration.ConfigurationManager.AppSettings["LogLevels"])) 
       { 

        string[] lls = System.Configuration.ConfigurationManager.AppSettings["LogLevels"].Split(",".ToCharArray()); 
        foreach (string ll in lls) 
        { 

         _logLevels.Add((LogLevel)System.Enum.Parse(typeof(LogLevel), ll)); 
        } 
       } 
      } 

      if (_logLevels.Count == 0) 
      { 
       _logLevels.Add(LogLevel.Error); 
      } 
      return _logLevels; 
     } 
    } 
} 

UPDATE : 나는 아래의 코드와 같이 정적 클래스에 동시성 문제를 해결하기 위해 스레드 동기화를 사용하여 끝났다.

public class Logger 
{ 
    private static readonly System.Object _object = new System.Object(); 

    private static List<LogLevel> _logLevels = null; 


private static List<LogLevel> LogLevels 
    { 
     get 
     { 
      //Make sure that in a multi-threaded or multi-user scenario, we do not run into concurrency issues with this code. 
      lock (_object) 
      { 
       if (_logLevels == null) 
       { 
        _logLevels = new List<LogLevel>(); 
        if (!string.IsNullOrWhiteSpace(System.Configuration.ConfigurationManager.AppSettings["SimpleDBLogLevelsLogger"])) 
        { 

         string[] lls = System.Configuration.ConfigurationManager.AppSettings["SimpleDBLogLevelsLogger"].Split(",".ToCharArray()); 
         foreach (string ll in lls) 
         { 

          _logLevels.Add((LogLevel)System.Enum.Parse(typeof(LogLevel), ll)); 
         } 
        } 
       } 

       if (_logLevels.Count == 0) 
       { 
        _logLevels.Add(LogLevel.Error); 
       } 
      } 
      return _logLevels; 
     } 
    } 
} 
+0

'public'이 아니라 귀하의 속성이 'private'입니다. – JerKimball

+0

수정자를 수정하여 public으로 변경했습니다. – Sunil

답변

3

속성이 다중 사용자 또는 다중 스레드 환경에서 동시에 사용하는 경우, 그것은 문제를 일으킬 수 있을까?

물론입니다. List<T>인 경우에만 개의 여러 독자 (작성자 없음)를 제외하고는 여러 스레드 용으로 설계되지 않았습니다.

'LogLevels'속성의 코드에 스레드 동기화를 사용해야합니까?

글쎄 한 가지 방법입니다. 또는 형식 초기화시 초기화 한 다음 읽기 전용 래퍼를 반환하십시오. (당신은 실제로 여러 스레드가 그것을 수정하고 싶지 않다.)

일반적으로 정적 생성자에서 상당한 양의 작업을하는 것은 bad idea이다. 이것이 실패하면,이 부동산에 대한 모든 접근이 영원히 실패 할만큼 행복합니까?

+0

... 아무도 그것을 액세스 할 수 없으면 (나는 그가 공개가 아닌 개인이 아닌 것을 의미한다고 생각한다.) – JerKimball

+0

Jon - 그래서 스레드 동기화를 사용하거나 속성 코드를이 클래스의 정적 생성자로 전송하라. 권리? 아니면 뭔가 다른 것을 의미합니까? – Sunil

+0

@Sunil : 그렇습니다.하지만 가장 중요한 것은 읽기 전용 래퍼입니다. –

3

이 코드는 경쟁 조건이 있으므로 여러 스레드에서 안전하게 실행할 수 없습니다. 가장 큰 문제는 List<T> 유형이 스레드 안전하지 않고이 코드가 자유롭게 쓸 수 있다는 것입니다. 이것은 쓰기가 병렬로 발생하여 암시 적 계약이 깨질 수 있음을 의미합니다. List<T>

1

짧은 대답은 "예"이고 "예"는 스레드 동기화가 필요합니다. 다른 질문은 바퀴를 다시 발명하는 이유는 무엇입니까? log4net 또는 .NET 로깅 프레임 워크와 같은 것을 사용할 수 있습니다.

+0

이러한 모든 로깅 프레임 워크의 문제점은 가파른 학습 곡선입니다. 내 개발자가 1 일째부터 로깅을 시작하고 싶습니다. 원하는 것은 데이터베이스에 로깅하는 것입니다. – Sunil

+0

천천히 복용 할 수 있습니다. 예를 들어 log4net의 기본 기능은 기본 구성뿐 아니라 비교적 간단하며 초보자도 몇 시간 안에 이해할 수 있습니다. 또는 lon4net을 중심으로 단순화 된 래퍼를 만들면 구성의 복잡성을 숨길 수 있습니다. – user1873415