VisualStudio/C#서버

[C#서버] TLS(Thread Local Storage) - 쓰레드로컬(ThreadLocal)

usingsystem 2022. 10. 26. 22:29
728x90

만약 멀티스레드 환경에서 수 많은 멀티스레드가 어떤 하나의 자원을 점유하고자 할 때 락이 잡혀 있다면 하나의 쓰레드 하나가 처리하는 속도 보다 못 할 수 있다. 이 때 쓰레드 각각 전용 공간에서 힙영역을 참조하면 효과적일 수 있다. 이러한 공간을 TLS라고 한다. (TLS의 하나의 예시일 뿐)

 

ThreadLocal

만약 아래와 같이 static으로 선언된다면 프로젝트 내에 여러 곳 에서 사용될 수 있어 쓰레드에게 영향을 미치지만 

ThreadLocal 키워드를 사용하면 각각 쓰레드마다 전용공간이 생긴 것 이기 때문에 다른 쓰레드에서 이름을 변경하여도 영향을 주지 않는다. 즉 공용 메모리를 사용하지 않는다.

   static ThreadLocal<string> ThreadName = new ThreadLocal<string>();

 

 internal class Program
    {
        static ThreadLocal<string> ThreadName = new ThreadLocal<string>();
        static void WhoAmi()
        {
            Thread.Sleep(1000);
            ThreadName.Value =  $"My Name Is{Thread.CurrentThread.ManagedThreadId}";
            Console.WriteLine(ThreadName.Value);
        }
        static void Main(string[] args)
        {
            ThreadPool.SetMinThreads(1, 1);
            ThreadPool.SetMaxThreads(3, 3);
            Parallel.Invoke(WhoAmi, WhoAmi, WhoAmi, WhoAmi, WhoAmi, WhoAmi);
        }
    }

결과

ThreadName에서 ThreadLocal을 빼고 string으로만 사용 할 경우

ThreadLocal 심화

ThreadPool환경에서 쓰레드 범위를 지정해주고 위와 같이 직접 ThreadLocal의 value값에 이름을 직접 넣어 준다면 위의 결과 처럼 사용하고 반납하고 다시 사용되는 쓰레드에 이름이 중복으로 들어가는 것을 볼 수 있다.

이미 한번 사용한 쓰레드라면 다시 이름을 넣어줄 필요가 없기 때문에 아래와 같이 수정할 수 있다.

ThreadLocal에 함수를 넣어 value를 넣어주게 된다면 이미사용한 쓰레드인지 판단하여 이름을 넣어준다.

    internal class Program
    {
        static ThreadLocal<string> ThreadName = new ThreadLocal<string>(() => { return $"My Name Is{Thread.CurrentThread.ManagedThreadId}"; });
        static void WhoAmi()
        {
            bool repeat = ThreadName.IsValueCreated;

            if (repeat)
                Console.WriteLine(ThreadName.Value + "(repeat)");
            else
                Console.WriteLine(ThreadName.Value);
        }
        static void Main(string[] args)
        {
            ThreadPool.SetMinThreads(1, 1);
            ThreadPool.SetMaxThreads(3, 3);

            Parallel.Invoke(WhoAmi, WhoAmi, WhoAmi, WhoAmi, WhoAmi, WhoAmi);
            ThreadName.Dispose();
        }
    }

ThredName.Dispose() - 자원해제

Parallel - 자동으로 쓰레드 생성해서 해줌. 테스트환경에서 편함.

728x90