반응형
고오급 식당
- 주문, 조리, 결제 등이 딱딱 아름답게 나뉘어 있지 않음
- 반드시 왔다갔다 해야 함
- 각 과정에 락을 다 걸어야 혼선이 생기지 않겠지?
- 여러 직원이 한 테이블의 일에 몰리지 않게
- 즉 게임으로 치면
- DB, 게임 로직, 클라이언트 세션, 로그 등
- 멀티쓰레드로 얘네의 일감 분배를 아름답게 해줘야겠지
- 무조건 멀티쓰레드라고 락 걸고 쓰레드를 늘리는게 능사가 아니다.
- 좁은 공간에 여러 직원이 들어가 봤자 일하기 더 불편해질 뿐이다
Thread Local Storage
- Stack 영역은 각 쓰레드에 별도로 존재
- 임시 메모리이므로 여기다가 무얼 저장한 다는 것은 불안정
- Heap, 데이터 영역은 모든 쓰레드가 공유
- 여기에다가 각 쓰레드의 개인 공간을 만들어 준다면?
- 이게 TLS의 개념
static ThreadLocal<string> ThreadName = new ThreadLocal<string>();
//전역에 저장되긴 하지만 각 쓰레드만의 공간에 저장됨
//다른 쓰레드에 영향을 주지 않음
static void WhoAmI()
{
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);
//인자로 넣은 것 각각을 Task로 만들어서 실행해줌
}
- 그냥 전역 string이 아닌, ThreadLocal<string>으로 래핑을 했기 때문에, 각 쓰레드마다 따로 관리가 들어감
- Paralle.Invoke로 6번 실행해 본다면?

- 래핑하지 않고 그냥 쓴다면, 모두 같은 값이 나온다.
- 만약, 쓰레드 개수의 최대 최소를 설정한다면?
- Parallel도 결국 풀링을 하는 애이기 때문에 중복된 쓰레드가 나올 수 밖에 없음
- 그러면 중복된 앤지 어떻게 구분하는가
static ThreadLocal<string> ThreadName = new ThreadLocal<string>(() =>
{
return $"My name is {Thread.CurrentThread.ManagedThreadId}";
}); //람다 함수로 선언과 동시에 값을 리턴
static void WhoAmI()
{
bool repeat = ThreadName.IsValueCreated; //value가 설정이 되었는지 아닌지 여부를 반환
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);
}
- 이렇게 처리할 수 있다.

- 만들어진 Value를 지우려면
- ThreadName.Dispose();
- 람다로 리턴했던 값을 지운다.
Thread Local Storage의 용도
- 우선 TLS에 저장된 값은, 자신만의 데이터이므로 락을 걸 필요가 없음
- 그러므로, 공용 공간에 접근하는 횟수를 줄이는 것 만으로도 의미가 있음
- 락을 잠갔다 풀었다 하는 오버헤드가 나오지 않음
- 즉, 락을 한 번 얻었을 때 TLS에다가 최대한 많이 뽑아 온다면, 다음엔 락에 접근할 필요가 없어지는 것
- Thread의 고유한 이름이나 ID 등을 사용해야 할 때 TLS를 사용하자
- 여기까지가 쓰레드의 기본기
반응형
'C# > 네트워크' 카테고리의 다른 글
[c#][서버] 소켓 프로그래밍 (0) | 2024.06.05 |
---|---|
[c#][서버] 네트워크 기초 이론 (0) | 2024.06.04 |
[c#][서버] ReaderWriterLock (0) | 2024.06.03 |
[c#][서버] Lock 구현 이론 (0) | 2024.06.02 |
[c#][서버] 데드락 (0) | 2024.06.02 |