📄 TLS

TLS(스레드 로컬 스토리지)는 스레드에 로컬인 정적 또는 전역 메모리를 사용하는 컴퓨터 프로그래밍 방법입니다.

이 기능은 정적, 전역변수를 각 스레드에게 독립적인 형태로 만들어주고싶을때 사용할 수 있습니다.

 

📑 정적 변수

namespace ServerCore
{
    class Program
    {
        static string ThreadName;
        
        static void WhoAmI()
        {
            ThreadName = $"My Name Is {Thread.CurrentThread.ManagedThreadId}";

            Thread.Sleep(1000);

            Console.WriteLine(ThreadName);
        }

        private static void Main(string[] args)
        {
            //Invoke에 넣는 액션만큼을 편리하게 태스크로 만들어 스레드풀에 있는 스레드가 호출하도록 함
            Parallel.Invoke(WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI);
        }
    }
}

 

각 스레드가 공유하는 ThreadName에서 같은 값으로 나온다

  • 태스크를 9개 사용한 상태에서 각 스레드가 출력하는 ThreadName이 모두 같은 결과로 나온것을 볼 수 있습니다.

 

📑 ThreadLocal

namespace ServerCore
{
    class Program
    {
        static ThreadLocal<string> ThreadName = new ThreadLocal<string>();
        
        static void WhoAmI()
        {
            //실제 타입(string)은 .Value에 있음
            ThreadName.Value = $"My Name Is {Thread.CurrentThread.ManagedThreadId}";

            Thread.Sleep(1000);

            //ThreadName.Value 출력
            Console.WriteLine(ThreadName.Value);
        }

        private static void Main(string[] args)
        {
            //Invoke에 넣는 액션만큼을 편리하게 태스크로 만들어 스레드풀에 있는 스레드가 호출하도록 함
            Parallel.Invoke(WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI);
        }
    }
}

 

하나의 변수를 사용하지만, 각 결과는 모두 다르게 나왔다.

static ThreadLocal<string> ThreadName
  • 정적 변수를 사용하지만, 결과는 각 스레드의 이름으로 출력되었습니다.
  • 스레드의 개수를 제한하지 않은 상태입니다.
  • 같은 변수 이름을 사용하여 출력하지만, 실제로는 스레드 각 주소공간을 사용하여 작업하는 것을 볼 수 있습니다.

 

namespace ServerCore
{
    class Program
    {
        static ThreadLocal<string> ThreadName = new ThreadLocal<string>(() =>
        {
            //ThreadName이라는 변수가 현재 값 생성이 안되어있다면, 생성
            return $"My Name Is {Thread.CurrentThread.ManagedThreadId}";
        });

        static void WhoAmI()
        {
            if (ThreadName.IsValueCreated) //이미 값이 있음
            {
                Console.WriteLine(ThreadName.Value + " 이미 생성됨");
            }
            else //최초로 만듬
            {
                Console.WriteLine(ThreadName.Value);
            }

            Thread.Sleep(1000);
        }

        private static void Main(string[] args)
        {
            //스레드풀의 크기를 제한한 상태에서 여러 태스크를 호출하면 대기해야함
            ThreadPool.SetMinThreads(1, 1);
            ThreadPool.SetMaxThreads(3, 3);

            Parallel.Invoke(WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI);

            ThreadName.Dispose(); //필요없어진경우 Dispose로 제거(모든 스레드 값 제거)
        }
    }
}

 

스레드풀의 스레드 개수를 최대 3개로 설정하였다.

 

static ThreadLocal<string> ThreadName = new ThreadLocal<string>(() =>
{
    //ThreadName이라는 변수가 현재 값 생성이 안되어있다면, 생성
    return $"My Name Is {Thread.CurrentThread.ManagedThreadId}";
});
  • TLS를 사용하는 스레드에서 현재 값이 생성되지 않은 상태라면, 람다표현식의 리턴값을 자신의 값으로 생성합니다.

 

if (ThreadName.IsValueCreated) //이미 값이 있음
  • 현재 값이 있는경우 확인할 수 있는 불리언 변수입니다.

'server > socket server' 카테고리의 다른 글

[C# 서버] Async Listener  (0) 2023.01.17
[C# 서버] 소켓 프로그래밍  (0) 2023.01.14
[C# 서버] ReaderWriterLock 구현  (0) 2023.01.11
[C# 서버] ReaderWriterLock  (0) 2023.01.10
[C# 서버] Mutex  (0) 2023.01.09
bonnate