프로세스와 스레드에 대해 먼저 알아보자.
프로세스 : 현재 실행 중인 프로그램
스레드 : 운영 체제가 프로세서 시간을 할당하는 기본 단위 / 명령어를 실행하기 위한 스케쥴링 단위
쉽게 말해서, 스레드는 작업자라고 생각하면 된다.
어떠한 업무가 주어졌을 때, 그 일을 수행하는 작업자가 바로 스레드 이다.
* NameSpace(네임스페이스) 선언하기
using System.Threading;
스레드를 사용하기 위해서 다음과 같이 선언해주자
1) 스레드 선언하기
Thread t = new Thread(MainTread);
스레드를 사용하기 위해 다음과 같이 스레드 생성자를 만든다.
넘겨주는 MainTread 함수 또한 생성한다.
static void MainTread(object state)
{
Console.WriteLine("Hello Thread!");
}
기본 스레드는 foreground에서 실행되는 형태이다.
스레드의 이름을 설정하고 싶으면 Name 을 활용한다.
static void Main(string[] args)
{
Thread t = new Thread(MainTread);
t.Name = "Test Thread"; //이름을 설정한다.
t.Start(); //스레드 실행
Console.WriteLine("Waiting for Thread!"); //메인 작업
}
이 때, 다음과 같이 스레드를 무한 반복으로 실행하면
메인 종료와 상관없이 계속해서 실행된다..
(foreground 스레드는 부모 스레드가 종료되어도 함께 종료되지 않고 계속 동작한다 )
static void MainTread()
{
//메인 함수와 상관없이 지속해서 실행됨(영영 실행..)
while(true)
Console.WriteLine("Hello Thread!");
이를 백그라운드에서 실행하면, 스레드는 실행 여부와 상관없이 메인 함수가 종료되면 같이 종료된다.
t.IsBackground = true; //기본 값은 false이다.
t.Start();
t.Join(); //스레드가 끝날 때 까지 기다림
join은 스레드가 종료될 때 까지를 기다린다. 즉, 스레드가 종료되었는 지를 확인하고 작업을 종료한다.
2) 스레드 풀(ThreadPool) 사용하기
thread 와 threadPool의 차이에 대해 먼저 알아보면,
thread
- 스레드를 사용할 때는 개수를 제한하지를 않는다.
- 하지만 스레드 수와 cpu core 수를 맞춰주는 것이 좋다
threadPool
- 스레드 풀을 사용하면 최대로 돌릴 수 있는 스레드를 제한한다.
- 아주 많은 개수를 실행시켜도 기존의 프로세스를 수행한 다음, 이후에 일을 수행한다.
ThreadPool은 단기로 실행하는 것에 대해 유용하다.
static void MainTread(object state)
{
for (int i = 0; i < 5; i++)
Console.WriteLine("Hello Thread!");
}
...
static void Main(string[] args)
{
ThreadPool.SetMinThreads(1, 1); //최소 스레드 개수
ThreadPool.SetMaxThreads(5, 5); //최대 스레드 개수
ThreadPool.QueueUserWorkItem(MainTread);
thread와는 다르게 object 인자를 명시해 주어야 하며 스레드의 개수를 제한하므로
setMinThread와 setMaxThread를 통해 최소, 최대 스레드를 설정해 주면 된다.
스레드 풀을 사용하여
최대 치 만큼 일을 할당하면
다음과 같이 이후의 일을 하지 못하는 것을 볼 수 있다.
하지만 다음과 같이 네 개의 스레드만 할당하여 남는 것이 있다면,
나머지 작업을 원활하게 수행 가능하다.
for (int i = 0; i < 4; i++)
ThreadPool.QueueUserWorkItem((obj) => { while (true) { } });
이처럼 모든 스레드가 할당 되었을 때, 일이 막히는 상황을 해결하는 방법은 무엇일까
Task를 사용하면 된다.
3) Task 사용하기
for(int i=0; i<5; i++)
{
//아주 오래걸리는 작업에 대해
Task t = new Task(() => {
while (true) { } }, TaskCreationOptions.LongRunning);
t.Start();
}
TaskCreationOPtions.LongRunning 옵션을 설정해주면, 긴 작업이 수행되는 작업에 대해서도
일을 원활하게 수행 가능하다.
이렇게 ThreadPool의 부족현상을 해결할 수 있다.
출처 및 참고 : https://www.inflearn.com/course/%EC%9C%A0%EB%8B%88%ED%8B%B0-mmorpg-%EA%B0%9C%EB%B0%9C-part4
'게임 서버 > Thread' 카테고리의 다른 글
[c#/유니티] DeadLock과 SpinLock에 대해 (0) | 2022.12.08 |
---|---|
[c#/유니티] 임계영역(Critical Section)을 위한 Monitor와 Lock (0) | 2022.12.07 |
[c#/유니티] Interlocked에 대해 (2) | 2022.12.07 |
[c#/유니티] 캐시(Cache) 이론과 메모리 배리어(Memory Barrier) (2) | 2022.12.06 |
[c#/유니티] 컴파일러 최적화 (1) | 2022.12.06 |