게임서버

쓰레드 기초

그린티라떼 2020. 11. 30. 00:06

개론

 

프로세스 = 프로그램

쓰레드 = 프로그램 안에서 일하는 직원

CPU코어 = 직원에게 명령을 내림

 

* CPU코어 1개 / 쓰레드 여러 개인 상황 : 코어가 아주 짧은 시간 번갈아 가면서 쓰레드에게 명령을 내림

 

 


쓰레드 생성

using System;
using System.Threading;

namespace ServerCore
{
    class Program
    {
        static void MainThread()
        {
            Console.WriteLine("Hello Thread!");
        }

        static void Main(string[] args)
        {
            Thread t = new Thread(MainThread);  //정직원 고용
            t.Start();  //일 시작 

            Console.WriteLine("Hello World!");
        }
    }
}

* 쓰레드을 많이 늘리면 쓰레드가 일하는 시간보다 코어가 명령을 내리는 부하가 훨씬 심하다.

* 컴퓨터에 내장되어있는 코어 수만큼 쓰레드를 만드는 것이 바람직하다.

 

t.name = "Test Thread"; //직원 이름 부여
t.IsBackground = ture; // Main()이 끝날때 같이 종료
t.Join() // 쓰레드가 끝날 때까지 기다림 

 

쓰레드풀 생성

 static void MainThread(object state)
        {
            Console.WriteLine("Hello Thread!");
        }

        static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(MainThread);  //인력 사무소 알바생 고용
            ...
        }

* 쓰레드풀은 최대로 동시에 돌릴 수 있는 쓰레드 수를 제한을 함

* 일할 쓰레드가 없을 시 기존에 작업하던 쓰레드가 일을 끝내고 돌아오면 재투입함(새로운 쓰레드 생성 x)

* 쓰레드풀은 가급적이면 짧은 일감을 줘야 함

 

ThreadPool.SetMinThreads(1, 1); // 최소 쓰레드 수
ThreadPool.SetMaxThreads(5, 5); // 최대 쓰레드 수

첫 번째 인자 : int workerThreads

두 번째 인자 : int completionPortThreads

 

 

ThreadPool.SetMinThreads(1, 1);
ThreadPool.SetMaxThreads(5, 5);
            
for (int i = 0; i < 5; i++)
    ThreadPool.QueueUserWorkItem((obj) => { while (true) { } });

ThreadPool.QueueUserWorkItem(MainThread);

* 쓰레드풀에 가급적 짧은 일감을 줘야 하는 이유, 위의 경우 MainThread를 실행 못함.

* 문제점을 해결하기 위해 태스크를 사용하자

 

태스크

            ThreadPool.SetMinThreads(1, 1);
            ThreadPool.SetMaxThreads(5, 5);

            for (int i = 0; i < 5; i++) 
            {
                Task t = new Task(() => { while (true) { } }, TaskCreationOptions.LongRunning);
                t.Start();
            }
             
            ThreadPool.QueueUserWorkItem(MainThread);

* LongRunning이란 쓰레드풀에 들어가긴 할 텐데, 오래 걸리는 작업이란 걸 알려주고 workerThreadPool에서 뽑아 쓰는 것이 아니라 별도 처리를 함

* Task는 LongRunning으로 쓰레드풀을 유연하게 사용할 수 있다.