본문 바로가기
게임개발/게임서버

TLS(Thread Local Storage)

by do_ng 2023. 10. 28.

멀티 스레드 환경에서 TLS를 사용하지 않은 경우

참고 :  https://code-piggy.tistory.com/248

동시성 문제가 발생하는 모든 구역에 Lock을 걸어버리면 데이터의 안전성은 보장되겠지만 상황에 따라서 문제가 발생할 수 있다. 

예를 들어서 게임로직에 A던전, B던전, C던전에 대한 코드가 작성이 되어 있는데 

갑자기 클라이언트 단에서 모든 유저가 A던전에 입장을 하려고 할 때 A 던전에 대한 게임로직이 바빠져서 평상시에 입장하는 것보다 시간이 더 오래 걸리게 될 수 있다. 

이러한 상황에서는 오히려 멀티 스레드로 환경을 구축하는게 더 안 좋게 된다. 

 

TLS를 사용해서 해결

참고 : https://learn.microsoft.com/ko-kr/windows/win32/procthread/thread-local-storage?redirectedfrom=MSDN

TLS( 스레드 로컬 스토리지 )를 사용하면 프로세스가 전역(Global) 인덱스를 사용하여 액세스할 수 있는 각 스레드에 대해 고유한 데이터를 제공할 수 있다.

 

각 쓰레드에 TLS 슬롯을 만들고 Globlal Data 영역에는 각 쓰레드의 TLS 슬롯과 연결되는 인덱스를 할당한다. 각 쓰레드는 TLS 슬롯 인덱스에 Globlal Data 영역 인덱스에 대한 포인터(주소)를 저장하고 그 포인터를 이용해 값을 가져와 각 쓰레드의 지역변수에 저장한다. 

 

코드

class Program
    {
        // Global 영역에 각각의 쓰레드가 독립적으로 TLS를 가짐
        static ThreadLocal<string> ThreadName = new ThreadLocal<string>();

        // TLS를 설정하지 않고 Global 데이터로 두게 되면 모든 스레드가 접근 할 수 있기 때문에 데이터가 변경 될 수 있음
        // static string ThreadName;

        static void WhoAmI()
        {
            // 쓰레드 이름을 추가하는 작업이 각각의 TLS에서 독립적으로 수행됨
            ThreadName.Value = $"My name is {Thread.CurrentThread.ManagedThreadId}";
            Thread.Sleep(1000);
            Console.WriteLine(ThreadName.Value);
        }

        static void Main(string[] args)
        {
            Parallel.Invoke(WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI);

            // Global 영역에 있는 TLS를 모두 해제
            ThreadName.Dispose();
        }
    }

'게임개발 > 게임서버' 카테고리의 다른 글

멀티 쓰레드 프로그래밍  (0) 2024.04.17
멀티쓰레드 Lock 구현 방식  (2) 2024.01.15
소켓 프로그래밍  (0) 2023.10.29
ReadWriteLock  (0) 2023.10.26
교착 상태(Deadlock)  (0) 2023.10.17