개인공부) 서버실습(16) - Thread Local Storage

Justin·2022년 6월 8일
0

서버공부

목록 보기
15/45
post-thumbnail
post-custom-banner

✅ 지난 시간

Read Write Lock을 구현하며 비트에 할당하는 부분이 잘 이해가 되지 않아 배우기 쉽지 않았다. 그래도 여러번 듣다보니 익숙해져서 결국 정리는 잘 해두었지만, 반복해서 보면서 내용을 잘 기억해야겠다.

💾 Thread Local Storage

개념설명
TLS 란 각 쓰레드간의 공유-개인 사이에 있는 듯한 저장 공간이다. 쓰레드의 구조가 heap, 데이터 영역은 서로 공유하고, Stack은 독립된 공간에서 사용한다.

하지만 이때 전역으로 설정하기엔 부담스럽지만, 쓰레드 들이 공통으로 사용될만한 영역을 제공해주는게 TLS이다.(쓰레들 간의 공유가 이루어지지는 않는 고유의 공간이다)

❓ 왜 사용하는걸까?

게임 서버 동작 시에 유저들이 한 쪽으로 모이면서 쓰레드들이 처리해야 할 일감의 쏠림현상이 발생할 수 있다.

상호배제를 위해 다 lock을 걸고하자니 병목현상이 발생 할 수 있어 이런 일감을 한 번에 각자 공간(TLS)으로 가져가 처리를 하는 방식에 사용될 수 있다.

📑 사용법

만약 Static string으로 전역 변수를 선언 해버리면, 다른 쓰레드에서 Write 할 경우 값이 변경되어 고유의 공간에 의미가 없다.

TLS를 만들기 위해서는 ThreadLocal 기능을 활용하면 된다.

선언을 해준 뒤에 _threadLocal.Value 에 각 쓰레드의 ID 값을 넣어보며 고유의 공간을 갖게 되는지 테스트를 해본다.

Parallel.Invoke() 간단 실행법
Parallel.Invoke()를 활용하면 ThreadPool에서 가져와 편하게 쓰레드를 호출할 수 있게해준다.

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

ThreadLocal.Value 값에 넣어주니 각 쓰레마다 다른 값을 출력하는 걸 확인 할 수 있다.

🟥 문제점 및 개선사항

위와 같은 구조로 사용 시 처음에 _threadLocal.Value에 이미 id가 들어갔어도, WhoAmI() 함수가 출력 될 때 마다 새로운 값을 덮어 씌우며 불필요한 행동을 한다.

이를 해결하기 위해 이미 있는 id라면 생성하지 않고 넘어가도록 구현해보자.

bool repeat = _threadLocal.IsValueCreated;

IsValueCreated를 활용하면 이미 제작되어 있을 경우 true 값을 return한다 이를 이용해 중복일 경우 구분을 해준다.

static ThreadLocal<String> _threadLocal 
= new ThreadLocal<String>(
() => { return 
$"My Name is:Thread.CurrentThread.ManagedThreadId}"; }  );

이런식으로 람다를 이용해 return 값을 주게 만들면, 계속 생성하는 것이 아닌 Value 값을 체크해서 없으면 return을 통해 만들고, 있다면 그냥 넘어가도록 하는 구조이다.

💨 TLS 제거하기

사용을 모두 했다면 Dispose() 함수로 간단하게 보내줄 수 있다.


오늘 배운 TLS라는 공간을 잘 활용하면 편하게 이런 저런 작업을 지시하고, 빠른 일감 처리가 가능해질 것 같다. 이제 전반적인 멀티 쓰레드에 대한 지식은 잡혀가고 있고, 다음 네트워킹도 기대가 된다잉

profile
인디 게임을 만들며 공부하고 있습니다.
post-custom-banner

0개의 댓글