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