TLS( Thread Local Storage)

이승한·2023년 12월 12일
0

Server

목록 보기
1/4
post-thumbnail

TLS

이번에 알아 볼 TLS는 우리가 어마어마한 작업을 한다 했을 때 우리의 모든 쓰레드들이 힙영역 전역변수 영역에 다 달라붙어서 작업을 하면 효율이 안좋을 것이다.
그러므로 각 쓰레드들마다 가지고 있는 고유의 작업 공간이라 생각하면 된다.

그래서 작업할 것들을 각자 한 움큼씩 가져와서 TLS에서 작업 한다 생각하면 된다.


일단은, 그냥 TLS를 사용하지않았을 때는 어떨지 알아보면

class Program 
{
    
    //static ThreadLocal<string> ThreadName = new ThreadLocal<string>();
    static string ThreadName;

    static void WhoAmI()
    {
        //다른 쓰레드들한테는 영향을 안주고 나의 영역에서만 
        ThreadName = $"My Name is {Thread.CurrentThread.ManagedThreadId}";
        Thread.Sleep(1000);
        Console.WriteLine(ThreadName);
    }

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

}

결과 값:

이렇게 같은 쓰레드가 사용되고 있다.


class Program 
{
    
    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)
    {
    	ThreadPool.SetMinThreads(1,1);
        ThreadPool.SetMaxThreads(3,3);
        Parallel.Invoke(WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI, WhoAmI);
    }

}

우리가 쓰고자하는 변수에 ThreadLocal을 sealing해주면 된다.

결과 값:

단점이라고 하면, 이미 같은 ThreadId로 한번 실행을 한 상태라서 자신의 Name을 가지고있으면 굳이 ThreadName.Value = $"My Name is {Thread.CurrentThread.ManagedThreadId}"이 부분을 다시 실행 안해도 되는데 계속 실행하는 문제가 있다.

이게 마음에 안들면,
ThreadLocal을 sealing할때 인자를 추가 할 수 있는데

//static ThreadLocal<string> ThreadName = new ThreadLocal<string>(Func<string> valueFactory) 인자 사용
//Func타입이니 람다식으로 간단히 만들어서 테스트
static ThreadLocal<string> ThreadName = new ThreadLocal<string>(() => {return $"My Name is {Thread.CurrentThread.ManagedThreadId}";});

이렇게 선언하면 쓰레드가 새로 실행될때마다 ThreadName을 만들어주는게 아니라 ThreadName의 Value가 세팅이 안됐으면 Value에다가 값을 넣어주게 된다.

그래서,

class Program
{
	static ThreadLocal<string> ThreadName = new ThreadLocal<string>(() => {return $"My Name is {Thread.CurrentThread.ManagedThreadId}";});
    
    static void WhoAmI()
    {
    	//이미 만들어져있으면 True로 반환해줌
    	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, WhoAmI, WhoAmI, WhoAmI);
    
    //ThreadName을 삭제하고싶으면
    ThreadName.Dispose();
	}
}

결과 값 :

0개의 댓글