메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

한빛랩스 - 지식에 가능성을 머지하다 / 강의 콘텐츠 무료로 수강하시고 피드백을 남겨주세요. ▶︎

IT/모바일

Perl 쓰레드 소개

한빛미디어

|

2001-11-30

|

by HANBIT

14,334

by 김진중 / 라이센스 : GPSL(http://shovel.ye.ro) 0. 머릿말 대부분의 사람들이 Perl에서 떠올리는 것은 CGI 프로그래밍일 것이다. 그러나 Perl은 CGI보다는 보통 시스템 관리나 기타 텍스트 처리를 하는 곳(로그 분석, 텍스트 검색 및 파싱 등)에 대체적으로 많이 쓰이고 있으며, 그 밖의 많은 곳에도 범용적으로 쓰이고 있다(라고는 하지만 흠..^^;;). 그런 범용 언어로써 Perl에 기본적으로 들어 있는 모듈들은 상당히 많다(표준 모듈이 아닌 CPAN에 있는 모듈까지 다 합한다면, 아마 자신이 모듈을 만들 필요는 없지 않을까 싶을 정도이다). 그 중에서 오늘은 아마 Perl을 안다고 하는 사람들의 대부분이 써보지 않았을 것 같은, 또는 "그런 모듈도 있었나?" 할만한 모듈인 쓰레드(Thread) 모듈에 대해서 "간단히" (-_-;;) 알아보고자 한다. 1. 쓰레드란? 이 글을 읽는 사람중에서는 "쓰레드란 무엇인가요?"라고 물어보는 사람은 없겠지만, 혹시나 모르는 분들을 위해서 역시 아주 "간단하게" 정리해보도록 하겠다.. (-_-;;) 한마디로 말해서 쓰레드란 경량화 프로세스(Light Weight Process-LWP)이다. 그리고 쓰레드는 프로그램을 통한 제어의 순차적인 흐름이라고 할 수 있으며, 그래서 다중 쓰레드 프로그래밍은 여러 제어 쓰레드가 한 프로그램에서 동시에 수행하는 병렬 프로그램의 한 형태라고 말할 수 있다.
Perl 프로그래밍
음... 그럼 쓰레드는 왜 쓰는가? 일단 프로세스 단위보다 가볍기 때문에 부하를 줄일 수 있고, 쓰레드간의 통신이 쉽고, 또한 서로 자원을 공유할 수 있다는 장점이 있다(그래서 "lock"이라는걸 잘 써야하기도 하다). 또 멀티 쓰레드를 이용하면 다중 CPU 시스템에서 여러 CPU 상에서 병렬적으로 수행될 수 있기 때문에 단일 쓰레드 프로그램보다 훨씬 효율적이고 빠르게 일을 처리할 수 있다(아.. 어떠한 프로그램이라도 쓰레드가 반드시 한개씩은 있다). 보통 멀티 쓰레드를 쓰는 프로그램은 대부분의 윈도우용 프로그램이며, 특히 서버 프로그래밍에 많이 쓰인다(잘 아는 웹 서버인 아파치도 2.0부터는 쓰레드를 이용한다). "당신 말로는 도대체 무슨 말인지 전혀 모르겠어!" 라고 말하는 사람은 trax님의 "C# 쓰레드 이야기"를 참고하기 바란다. 2. 쓰레드 모듈 소개 쓰레드 모듈은 Perl 버전 5.005부터 지원하기 시작했다. 5.6의 쓰레드 방식은 5.005와는 좀 다르지만 그러나 여전히 5.005 방식의 쓰레드도 지원하며, 만약 쓰레드를 쓴다면 5.005의 쓰레드 방식을 권장하고 있다. 아! 버전에 관해서 5.005와 5.6이 차이가 많이 나는 건 사실이지만 엄청나게 바뀌어서 숫자가 많이 올라간 것이 아니라, 버전 형식이 바뀐 것이다. Perl의 버전 명명법은 대개의 오픈 소스들의 버전 명명법과 좀 틀려서 5.6 버전부터 일반적인 오픈 소스들의 버전 명명법으로 바뀐 것이다. Perl 5.6에서 세세한 것이 많이 바뀌긴 했지만 그래도 역시 가장 중요한 점은 유니코드의 지원 강화이다. 그래서 이 문서에서는 5.005 형식의 쓰레드 모듈을 살펴본다. 3. 쓰레드를 사용을 위한 컴파일하기 MS Windows 계열에서는 ActiveState에 가서 쓰레드를 지원하는 펄을 가져다가 설치하면 되고 Unix 계열에서도 역시 바이너리로 있는 것으로 알고 있지만.. 삽질을 좋아하는 성격상 (-_-;;) 직접 컴파일 하는 법을 알아보기로 한다. 일단 Perl의 소스를 http://www.cpan.org에 가서 받아온 후(최신 안정버전은 5.6.1이다. 개발버전은 5.7.1) EADME.threads를 읽어 보면 다 나온다. 컴파일 방법은 매우 쉽다. 소스를 풀어 놓은 후 소스 디렉토리 안에 들어가서 다음과 같이만 하면 된다.
sh Configure -Dusethreads -Duse5005threads
make
make test
make install (물론 root로..)
여기에서는 5.005 버전의 쓰레드를 사용하기 때문에 use5005threads 옵션을 주었다. 그리고 아무 에러 없이 컴파일이 성공하면, 쓰레드 사용 준비 끝! 4. 단일 쓰레딩 Perl로 쓰레드 프로그래밍은 처음이니, 아주 간단한 쓰레드를 한 번 만들어 보자.
use Thread;

$thr = new Thread ₩&sub1;

sub sub1 {
   print "In the thread₩n";
}
엇..너무 간단한가..? 마치 "hello world"를 찍고 "나는 프로그래머야~"라고 외치듯이, 쓰레드 한 개를 생성했더라도 이것은 쓰레드 프로그램이다! 여하튼, Perl에서의 쓰레드 사용은 매우 간단하다. 일단 use Thread로 쓰레드를 사용할 수 있도록 정의하고, new 메소드를 이용하여 sub1의 함수의 레퍼런스를 만든다. 그리고 쓰레드에 변수를 넘겨 주고 싶을 때는 다음과 같이 하면 된다.
use Thread;

@param = qw( perl foo bar );

$thr = new Thread ₩&sub1, "perl", "foo", "bar";
$thr = new Thread ₩&sub1, @param;
$thr = new Thread ₩&sub1, qw( perl foo bar );

sub sub1 {
   my @parameters = @_;
   print "In the thread₩n";
   print "parameters : ", join(", ", @parameters), "₩n";
} 
너무 간단하기 때문에 설명을 안해도 다 알리라 생각한다.. ㅡㅡ;; 위의 방식 말고 쓰레드를 생성하는 다른 방법이 있다. 바로 다음과 같이 async를 이용하는 것이다.
use Thread qw(async);

$thr = async {
   foreach (1..10) {
      print "$_ line in thread₩n";
   }
};

print "Start thread...₩n";
$thr->join;
print "All done₩n";
음.. 이미 다 알겠지만 이것을 사용할 때 async 문은 블럭 구문이기 때문에 닫는 브레이스에 세미콜론을 반드시 붙여줘야한다. 역시.. 너무 간단하기 때문에 설명은 필요 없을 듯..ㅡㅡ; 음..그리고 또 뭘 해야하지?..아하하.. ^^;; 대책없이 글을 쓰는 티가 나는군.. ㅡㅡ;; 다음은 쓰레드에서 결과값을 받아오는 방법에 대한 소스이다.
use Thread;

$thr = new Thread ₩&sub1;

@result = $thr->join;
print "Thread returned @result₩n";

sub sub1 {
   return "perl", "foo", "bar";
}
자.. 역시 너무나 간단하다.. 여기서 Join 메소드는 예상한바와 같이 join은 쓰레드가 끝날 때까지 기다려서 쓰레드에게서 반환값을 받아온다. 그러나 쓰레드가 끝날 때까지 기다리기 싫거나, 받아올 값이 없으면 다음과 같이 detach 메소드를 쓰는게 좋다.
use Thread;

$thr = new Thread ₩&sub1;

$thr->detach;

sub sub1 {
     $i = 0;
     while (1) {
	$i++;
	print "₩$i = $i₩n";
     }
}
join과 detach의 차이점은 다음의 멀티 쓰레드 절에서 보여질 것이다. 자.. 쓰레드를 잘못쓰면 자료가 뒤죽박죽이 되는 경우가 있다. 그것은 쓰레드가 한 프로세스 내의 자료를 공유하기 때문인데, 그것을 방지하기 위하여 Perl에서는 lock이라는 메소드를 제공하고 있다.
use Thread qw(async);

$a = 1;

$thr1 = async {
   $foo = 10;
   {
      lock ($a);
      $b = $a;
      $a = $b + $foo;
   }
   print "₩$foo was $foo₩n";
};

$thr2 = async {
   $bar = 5;
   {
      lock ($a);
      $c = $a;
      $a = $c + $bar;
   }
   print "₩$bar was $bar₩n";
};

$thr1->join;
$thr2->join;
print "₩$a is $a₩n";
lock 메소드는 $a의 값을 두 쓰레드가 동시에 쓸 수 없도록 방지해준다. lock 메소드에는 스칼라 값 뿐만이 아니라 배열이나 해쉬에도 적용 할 수 있다. 또한 함수에도 lock을 걸 수 있는데 그것은 다음과 같이 간단하게 할 수 있다.
sub sub1 :locked {
   pass;
}
지면 관계상(지면에 제약이 있나?;;.. 사실 귀찮아서..( ㅡ ㅡ);;:) 자세한 예제는 생략하기로 하고, 다음은 쓰레드의 백미! 멀티 쓰레드에 대해서 알아보도록 하자. 5. 멀티 쓰레딩 단일 쓰레딩이 쉬웠던 만큼 Perl에서의 멀티 쓰레딩 역시 쉽다. 백문이불여일견이라고 했던가? 일단 소스부터 보자.
use Thread;

my $t1 = new Thread ₩&start_sub;
my $t2 = new Thread ₩&start_sub;

$t1->detach;
$t2->detach;

while (1)
{
     print "I am the main thread₩n";
       sleep 1;
}

sub start_sub
{
  my $tid = Thread->self->tid;
  # self는 쓰레드 자신을 말하는 것이고 tid는 쓰레드의 id이다.
  # 그러고보니 주석 처음 달아보는군..ㅡ_ㅡ;;

    while (1)
    {
       print "I am thread $tid₩n";
       sleep 1;
    }
}
자.. 너무너무 간단하지 않은가? 그냥 생성하고 싶은 쓰레드의 수 만큼 레퍼런스만 생성해 주면 된다. 아마 너무 간단해서 속은 기분이 들 정도일 것이다. 여기서 주의해서 봐야 할 것이 있다. 위의 소스에서 detach 메소드를 join 메소드로 바꿔보고 실행해보라. 그러면 join과 detach의 차이를 알 수 있을 것이다. 간단하게 말하자면 detach는 쓰레드를 백그라운드로 실행시켜주는 것이라고 생각하면 될 것이다. 6. 더 해야할 것... 이 문서는 아주 단순히 Perl 쓰레드를 소개하고자 하는 것이 목적이었으므로(어디에도 Perl 쓰레드에 대해서 소개해 놓은 글이 없다!) 이정도 까지만 쓰려고 한다. 이정도만 해도 어느 정도까지의 활용은 가능하다고 본다. 물론 이 문서에 있는 것 외에도 할 것은 많다. 쓰레드에서의 에러처리라던가, 쓰레드 제어, 또한 쓰레드 모듈에 포함되어 있는 Queue 모듈, Semaphore 모듈, Specific 모듈 등을 더 알아봐야 할 것이다. 그러나 이 이상을 쓰는 것은 내 능력으로는 역부족이 아닌가 싶다..ㅡ_ㅡ;; 쓰레드 말고도 Perl 5.6에는 유니코드가 아직 불완전하지만 지원되어 있고, CPAN에는 여러가지 재미있는 모듈들이 많다. 그러한 것들을 모두 소개할 수는 없지만, 앞으로 조금씩 조금씩 Perl의 깊은 곳에 대해서 파헤쳐 볼 생각이 별로.. ^^;; 하하~ 자 모두들 Happy Hacking!! 7. 참고한 것 perldoc의 perlthrtut뿐..ㅡ_ㅡ;; 하지만 굉장히 잘 되어 있다. 여기 있는 소스도 거의 그곳에 있는 걸 조금씩만 변형한 것이다. 영어라 문제지.. ^^;;
김진중님은 매일매일을 숫자와 컴퓨터 프로그래밍으로 보내고 있는 프로그래머로 그들만의 세계에서는 nuthack으로 통합니다. Perl, Python, Ruby 등의 언어를 다루지만, 가장 이쁘고 아름다운 언어는 Perl이라고 우기는 Perl 예찬론자이며 모든 사람들이 Perl의 아름다움에 매료되었으면 하는 Perl 프로그래머입니다.
TAG :
댓글 입력
자료실

최근 본 상품0