티스토리 뷰
Thread 란?
여기서는 전문적인 내용이 아닌 심플하게 사용하는 방법만 언급하겠습니다.
하나의 프로그램 내에서 여러개의 실행 흐름을 두기 위한 모델입니다. 흠.. 설명이 좀 쉽지 않네요. 쉽게 말하면 동시에 여러 일을 처리하는 것 입니다.
예를 들어서
int n = 0;
for (int i=0;i<10000;i++)
{
n += i + 1;
}
printf( "sum : %d", n);
1 ~ 10000 까지 더하는 소스입니다. 저 소스에서 for 문에 진입해서 빠져 나오기까지 프로그램은 먹통같은 느낌이 됩니다. 만일 실수로 for문을 잘 못 적으면 무한루프에 빠지게 된다.
for (int i=0;i<10000;i--)
무한 루프에 빠지는 코딩이다
쓰레드를 사용하면 먹통되는 느낌을 막을 수 있습니다. 하지만 먹통되는 코딩을 하면 안되겠지요. 버그 발생은 시키지 맙시다.
컴퓨터에서 프로그램을 실행하게 되면 cpu에서 프로세스를 생성합니다. 프로세스를 동시에 여러개 처리 할 수 있는 기능이 쓰레드입니다. 쓰레드는 프로세서가 프로세스 작업을 처리하기 위해 할당 한 프로세스 수행 시간을 쪼개서 여러개의 작업을 수행 할 수 있도록 만든 방법입니다. 그리고 쓰레드는 여러 개념이 있는데 여기서는 간단하게 사용할 수 있는 중심으로 한 예를 들어서 하겠습니다.
class ExThread
{
void init()
{
// 파라미터 없는 ThreadStart 사용
Thread t1 = new Thread(new ThreadStart(Run));
t1.Start();
// ParameterizedThreadStart 파라미터 전달
// Start()의 파라미터로 radius 전달
Thread t2 = new Thread(new ParameterizedThreadStart(Calc));
t2.Start(10.00);
// ThreadStart에서 파라미터 전달
Thread t3 = new Thread(() => Sum(10, 20, 30));
t3.Start();
}
void Run()
{
Console.WriteLine("Run");
}
// radius라는 파라미터를 object 타입으로 받아들임
void Calc(object radius)
{
double r = (double)radius;
double area = r * r * 3.14;
Console.WriteLine("r={0},area={1}", r, area);
}
void Sum(int d1, int d2, int d3)
{
int sum = d1 + d2 + d3;
Console.WriteLine(sum);
}
}
위 소스가 쓰레드를 사용하는 예제입니다. 여기서 사용하는 예제에서 중요하게 봐야 하는 것은 파라미터 유무에 따라서 코딩이 달라지는 것입니다. 파라미터가 전달 하는 방법은 두가지 방법이 있는데 둘 중 아무거나 처리하면 됩니다.
그리고 꼭 기억해야 할 함수가 있습니다. Start() Join() Abort() 세가지만 기억합시다. 시작이고 대기이고 강제종료입니다. Start()만 기억하면 문제 될 것이 없습니다.
Thread 를 사용하면 임계영력 개념도 알아서 Lock 처리를 해야 하지만 그건 따로 찾아 보시면 됩니다.
C#에서 Thread 를 하다 보면 에러를 보게 됩니다. Main Thread 가 아닌 곳에서 File 읽기나 UI 처리를 하려고 하면 에러가 생깁니다. 만일 처리하고자 한다면 쓰레드에서 변수에 담아 두시고 Main에서 읽어서 처리하면 됩니다. 이럴때 Lock 처리가 필요합니다.
class MyClass
{
private int counter = 0;
public void Run()
{
// 10개의 스레드가 동일 메서드 실행
for (int i = 0; i < 10; i++)
{
new Thread(UnsafeCalc).Start();
}
}
// Thread-Safe하지 않은 메서드
private void UnsafeCalc()
{
// 객체 필드를 모든 스레드가 자유롭게 변경
counter++;
// 가정 : 다른 복잡한 일을 한다
for (int i = 0; i < 10000; i++)
for (int j = 0; j < 10000; j++);
// 필드값 읽기
Console.WriteLine(counter);
}
}
위와 같이 코딩하면 원하지 않는 결과를 초래할 수 있습니다. 그래서 아래와 같이 수정이 필요합니다.
class MyClass
{
private int counter = 0;
// lock문에 사용될 객체
private object lockObject = new object();
public void Run()
{
// 10개의 스레드가 동일 메서드 실행
for (int i = 0; i < 10; i++)
{
new Thread(SafeCalc).Start();
}
}
// Thread-Safe 메서드
private void SafeCalc()
{
// 한번에 한 스레드만 lock블럭 실행
lock (lockObject)
{
// 필드값 변경
counter++;
// 가정 : 다른 복잡한 일을 한다
for (int i = 0; i < 10000; i++)
for (int j = 0; j < 10000; j++);
// 필드값 읽기
Console.WriteLine(counter);
}
}
}
lock 반드시 사용해야 합니다. 그리고 mutex 나 semaphore 가 있는데 이 내용도 많으니 찾아서 알아두시면 됩니다. 쓰레드는 책 한권 정도의 분량이 될 만큼 개념과 상황별 어떻게 적용할지가 많으니 깊이 공부하고 싶으면 찾아서 보시면 됩니다.