by 한동훈(traxacun@unitel.co.kr)
요구사항: .NET Framework SDK beta 2
우리가 흔히 사용하고 있는 OS는 "멀티 OS"라고 한다. 이것의 의미는 동시에 여러 가지 작업을 한다는 것을 뜻한다. MP3를 들으며 워드를 작성하면서 인터넷 서핑을 할 수 있다.
이때 각각의 응용 프로그램은 하나의 프로세스를 갖는다. 그러니까 MP3 플레이어도 하나의 프로세스이고 워드 프로세서도 하나의 프로세스이고, 인터넷 브라우저도 하나의 프로세스라는 뜻이다.
반면에 쓰레드는 프로세스를 여러 개로 나눈 조각과 갖다고 설명할 수 있다.
워드 프로세서를 사용하는 경우를 예로 들자. 워드에서 글자를 입력하는 동안 파일을 디스크에 저장하고 있고, 내용을 프린터에 출력하고 있고, 입력하는 동안에 맞춤법 검사를 수행한다. 사용자의 입력을 받는 동안 행하는 이 모든 작업들은 각각의 쓰레드에 의해서 이루어진다. 글자를 입력 받는 쓰레드, 파일을 디스크에 저장하는 쓰레드, 출력할 내용을 프린터에 보내는 쓰레드, 입력하는 동안 맞춤법 검사를 수행하는 쓰레드 등이 있다. 즉, 워드 프로세서라는 큰 프로세스 하나에 여러 개의 쓰레드가 모여있는 것이다.
실제로 프로세스는 하나의 어드레스 공간을 갖고 있고, 모든 응용 프로그램은 메인 응응 프로그램을 위한 하나의 쓰레드를 갖는다. 그리고 여기에 다른 쓰레드들이 함께 수행될 수 있고, 각각의 쓰레드들은 자신을 관리하는 프로세스의 어드레스를 갖고 있다. 즉, 프로세스는 쓰레드에 대한 일종의 컨테이너역할을 한다.
쓰레드를 이용하면 얻을 수 있는 이점은 무엇인가?
사실 필자는 쓰레드를 그다지 이용하지 않기에 잘 모르지만, 다른 사람들의 얘기를 들어보면 잘 쓰면 명약이요, 잘못 쓰면 독약인 것이 쓰레드라고 하는 것 같다.
쓰레드를 이용하면 하나의 프로그램에서 한 번에 하나의 일을 처리하는 것이 아니라 동시에 많은 일을 처리할 수 있다는 장점이 있다. 뿐만 아니라 같은 일을 더 빠른 시간안에 처리할 수 있을 것이다. 처리 시간이 오래 걸리는 작업에 대해서 쓰레드에게 처리를 맡기고, 다른 일을 계속해서 처리할 수도 있는 것이다.
다음 그림을 보도록 하자.
그림에서처럼 하나의 프로세스에서 처리해야하는 세 가지의 작업 A, B, C가 있고 각각의 처리시간이 위의 길이와 같다고 할 경우에 첫번째와 같이 순차적으로 처리하는 경우보다는 두 번째와 같이 쓰레드를 이용하여 동시에 처리하는 것이 처리시간이 더 짧다는 것을 알 수 있을 것이다.
이러한 쓰레드의 위력은 많은 동시 사용자를 처리하는 환경이나 한 번에 많은 작업을 처리하는 응용 프로그램에서 그 위력을 발휘할 것이다.
이제 간단한 쓰레드 프로그램의 예제를 살펴보도록 하자.
SimpleThread.cs
using System;
using System.Threading;
public class Tester
{
public static void Main()
{
Tester t = new Tester();
t.DoTest();
}
public void DoTest()
{
Thread t1 = new Thread(
new ThreadStart(WorkerThreadMethod) );
Console.WriteLine("쓰레드를 생성");
t1.Start();
Console.WriteLine("쓰레드 시작을 요청 받았음");
}
public void WorkerThreadMethod()
{
Console.WriteLine("WorkerThreadMethod 시작했음");
}
}
|
각각의 코드를 살펴보도록 하자.
using System;
using System.Threading;
|
System은 C#에서 응용 프로그램 개발에 있어서 필요하며 여기서는 Console.WriteLine을 사용하기 위해 선언했다. 중요한 것은 두 번째 문장으로 쓰레드 프로그래밍을 하기 위해서는 System.Threading 네임 스페이스를 선언하기만 하면 된다.
(아… 깜빡한 사실이 있는데, C#에서는 쓰레드를 지원한다. Java의 쓰레드와 비슷하다고 생각하면 된다. C#과 Java의 쓰레드 지원에 대한 논의는
쓰레드, 그리고 Java와 C#을 참고하기 바란다)
public class Tester
{
public static void Main()
{
Tester t = new Tester();
t.DoTest();
}
|
Tester라는 임시 클래스를 만들었고 Main() 함수를 선언했다. 여기서는 Main() 함수에 직접 함수를 두지 않고 DoTest()와 같은 별도의 함수를 만들어서 처리하고 있다.
Main()은 응용 프로그램의 진입점(entry point)으로 사용하고, 실제 처리 코드는 별도의 함수로 만들어서 처리하는 것을 권한다.
Thread t1 = new Thread(
new ThreadStart(WorkerThreadMethod) );
|
여기는 쓰레드를 생성하는 부분이다. t1이라는 쓰레드를 생성하고, 쓰레드에서 호출할 함수는 ThreadStart(WorkerThreadMethod)와 같이 사용한다. WorkerThreadMethod()는 함수이므로 ThreadStart(WorkerThreadMethod())와 같이 사용해도 된다. 주의할 점은 ThreadStart에 지정하는 함수는 반드시 void 함수이어야 한다는 것이다.
쓰레드의 시작을 요청한다. Start() 함수를 만나기 전까지 쓰레드는 시작되지 않는다는 것도 알아두자.
public void WorkerThreadMethod()
{
Console.WriteLine("WorkerThreadMethod 시작했음");
}
|
쓰레드가 사용하는 함수를 정의한 부분이다. 위에서 알 수 있는 것처럼 쓰레드에 의해서 호출되는 메소드는 반드시 void형으로 정의해야 한다.
다음에는 여러 개의 쓰레드를 동시에 처리하는 멀티쓰레드에 대해서 알아보도록 하자. 그때까지 심심하더라도 잘 지내기 바란다.