[C#] Thread Safety 쓰레드 안전이란?

|


Thread Safe란  클래스나 함수, 객체등이 멀티쓰레드 환경에서 정상적으로 동작을 보장하는 것을 의미한다.

아래의 예제들을 통해서 쓰레드 안전한 코드와 안전하지 않는 코드를 살펴보고, 쓰레드 안전하게 만들 수 있는 방법들을 검토해 보겠습니다.



1.쓰레드 안전하지 않는 코드의 예

class NoThreadSafeClass
{
    private int UserAccessCount = 0;

    public int getNowAccessCount()
    {
        UserAccessCount = UserAccessCount + 1;
        return UserAccessCount;
    }
}

+위의 클래스가 현재 접속한 사용자의 횟수를 리턴하는 함수가 있어서 여러 쓰레드에서 동시에 getNowAccessCount() 메소드를 호출 한다고 할 때, 해당 쓰레드가 접속 할 때의 횟수를 리턴 받는다고 보장 못한다. 하나의 쓰레드에서 UserAccessCount를 증가 시키고 리턴받기 전에 다른 쓰레드에서 UserAccessCount를 증가 시킬수 있는 상황이 존재하기 때문이다. 즉 접속해서 1의 결과가 와야되는데 2이상이 올 수 있다는 이야기 이다. 



2.쓰레드 안전한 코드의 예

class ThreadSafeClass
{
      private int UserAccessCount = 0;
      private Object thisLock = new object();

      public int getNowAccessCount()
      {
          lock (thisLock)
          {
              UserAccessCount = UserAccessCount + 1;
              return UserAccessCount;
           }
            
       }

       public string getUpperCase(string willToUpperCaseName)
       {
            string UpperCaseName;
            UpperCaseName = willToUpperCaseName.ToUpper();
            return UpperCaseName;
        }
}

+위에서는 2가지의 함수가 존재한다. 모두 쓰레드 안전하다. 위 1번의 쓰레드 안전하지 않는 코드를 쓰레드 안전하게 변경하려면 lock구문을 써서 동시에 UserAccessCount를 증가시키지 못하게 처리하면 된다. getUpperCase 함수도 쓰레드 안전하다. (getUpperCase처럼 함수를 만드는 경우는 없겠지만 설명용으로만 사용되는 소스니 이해 바랍니다.)  함수 자체의 로컬 변수를 사용하므로 여러 쓰레드에서 동시에 호출에도 다른 쓰레드에 영향을 받지 않는다.



3.쓰레드 안전한 코드를 만드는 방법


1.무엇보다 공유자원을 사용하지 않는다. 로컬변수를 사용함으로 써, 각각의 쓰레드가 자신만의 변수를 가지게 한다.


2.불변의 객체(Immutable Object)를 만든다. 클래스를 만들 때, 내부 변수를 변경 불가능하게 만든다. 한번 초기화 될 때 생성자에 의해서 내부 변수가 설정이 한번 되면 변경이 불가능해야한다. +여기서 주의 할 점은 클래스이 내부의 멤버변수를 참조형 자료타입이면 setter가 없더라도 참조된 객체를 통해서 외부에서 변경을 할 수 있는 가능성이 있습니다.  참조형 자료타입이면 생성자에서 새로 객체를 생성해서 값을 복사해야 한다. 


3.불가피하게 공유자원을 사용하려면 상호배제(Mutual exclusion)를 해야한다. 공유자원에 접근시에 lock을 걸어서 여러 쓰레드에서 하나의 자원을 동시에 점유하지 못하게 처리한다.






And