[Server] 멀티쓰레드
Thread
CPU 수행의 기본 단위
Task
스레드가 수행되는 환경
> 프로세스는 하나의 스레드가 있는 Task와 일치
스레드는 Thread ID, Program counter, Register set, Stack space로 구성
스레드는 자신의 레지스터 상태와 스택 을 지님
Code, Data 섹션이나 운영체제 자원들은 스레드끼리 공유
종류
싱글 스레드(Single thread)
하나의 스레드를 이용하여 한 번에 한 작업만 수행하는 것은
멀티 스레드(Multi thread)
한 프로세스가 여러 스레드로 동시에 여러 작업을 수행하는 것
장점
병렬성(Parallelism)
- 프로세스의 스레드들이 각각 다른 프로세서에서 병렬적으로 수행
동시성(Concurrency)
- 실제로는 각각의 시간에 한 작업만 수행되지만, 병렬적으로 수행되는 것처럼 보이는 것
응답성(Responsiveness)
- 작업을 분리해서 수행하므로 실시간으로 사용자에게 응답
자원 공유(Resource sharing)
- 프로세스는 오직 공유 메모리나 메시지 패싱을 이용해서 자원을 공유
- 스레드는 자신이 속한 프로세스 내의 스레드들과 메모리나 자원을 공유하여 효율적으로 사용
경제성(Economy)
- 프로세스를 새로 생성하는 비용보다 스레드를 새로 생성하는 게 훨씬 쌈
- Context switching의 오버헤드 또한 스레드가 더 경제적
확장성(Scalability)
- 멀티 스레드인 경우 한 프로세스를 여러 프로세서에서 수행할 수 있으므로 훨씬 효율적
쓰레드 생성 (C#)
using System;
namespace Server
{
class Program
{
static void MainThread(object state)
{
while (true)
{
Console.WriteLine("Tread");
}
}
static void Main(string[] args)
{
Thread t = new Thread(MainThread);
t.IsBackground = true; // true 일 경우 Main 이 끝날 때 Thread 도 종료
t.Start();
t.Join(); // 끝날 때 까지 Wait
Console.WriteLine("Main");
}
}
쓰레드 풀 사용 (C#)
using System;
namespace Server
{
class Program
{
static void MainThread(object state)
{
while (true)
{
Console.WriteLine("Tread");
}
}
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(MainThread);
Console.WriteLine("Main");
while (true)
{
}
}
}
}
쓰레드 풀 먹통만들기 (5개의 쓰레드 모두 무한반복 작업)
using System;
namespace Server
{
class Program
{
static void MainThread(object state)
{
while (true)
{
Console.WriteLine("Tread");
}
}
static void Main(string[] args)
{
ThreadPool.SetMinThreads(1, 1);
ThreadPool.SetMaxThreads(5, 5);
// 무한반복
for (int i = 0; i < 5; i++)
{
ThreadPool.QueueUserWorkItem((obj) => { while(true){} });
}
ThreadPool.QueueUserWorkItem(MainThread);
}
}
}
해결방안 - Task 사용
using System;
namespace Server
{
class Program
{
static void MainThread(object state)
{
while (true)
{
Console.WriteLine("Tread");
}
}
static void Main(string[] args)
{
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();
}
// // 무한반복
// for (int i = 0; i < 5; i++)
// {
// ThreadPool.QueueUserWorkItem((obj) => { while(true){ } });
// }
ThreadPool.QueueUserWorkItem(MainThread);
}
}
}
오래 사용할 일을 Task를 이용하여 관리가능