Recommanded Free YOUTUBE Lecture: <% selectedImage[1] %>
Docbook 원문

쓰레드 우선순위 문제 해결

쓰레드 우선순위 문제 해결

윤 상배

dreamyun@yahoo.co.kr

교정 과정
교정 0.82003년 8월 3일 18시
최초 문서작성

차례
1절. 소개
2절. 문제 발생
3절. 문제 해결
4절. 결론

1절. 소개

프로그래밍(:12)을 하다보면 "분명 이러한 상황에서는 이러한 문제가 발생하지 않아야 하는데", "코드 상으론 아무런 문제가 없는데" 프로그램의 실행에 문제가 생기는 경우가 있다.

pthread(:12)를 이용해서 쓰레드:::프로그래밍(:12)을 할때도 이런 일이 간혹 발생한다. 이중 "쓰레드 우선순위"에 따라서 발생하는 문제점에 대해서 알아보겠다. 이 문제는 주의해서 프로그래밍 하지 않을 경우 간혹 발생하기도 한다.

이 글은 여러분이 pthread를 이용한 쓰레드 프로그래밍에 대한 기본적인 이해를 가지고 있다는 가정하에 씌여져 있다. 예제로 제시된 코드의 테스트는 리눅스(kernel-2.4.x)와 솔라리스 5.7환경에서 이루어 졌다.


2절. 문제 발생

다음은 이번 테스트에 사용될 예제코드다.

예제 : thread_test.c

#include <pthread.h>
#include <sys/wait.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

void *threadfunc(void *arg);

main()
{
    int n, i, j;
    pthread_t threadid;

    if ((n = pthread_create(&threadid, NULL, threadfunc, NULL)) != 0 )
    {
        perror("Thread create error ");
        exit(0);
    }
    printf("Main Thread START\n");
    for (i = 0; i < 100000000; i++)
    {
        j = i*5;
    }
    printf("Main Thread END\n");
    pthread_join(threadid, NULL);
}

void *threadfunc(void *arg)
{
    int i, j;
    printf("Thread Start\n");

    for (i = 0; i < 100000000; i++)
    {
        j = i*5;
    }

    printf("Thread:end\n");
    return ;
}
		
코드는 최소한의 테스트가 가능한 수준에서 작성되었다. 위의 코드는 언뜻 보기에 아무 문제가 없을 것 같고, 실제 특정 플랫폼에서는 문제 없이 작동하지만 플랫폼을 이동했을 경우 상당히 심각한 문제가 발생한다.

위의 코드를 리눅스(:12)에서 컴파일 시켜서 실행 시켜보면 아래와 같은 출력 결과 물을 보이면서 정상적으로 작동하는걸 확인 할 수 있을 것이다.

[root@localhost test]# ./thread_test 
Main Thread START
Thread Start
Main Thread END
Thread:end
		
그러나 위의 예제를 솔라리스(:12)에서 컴파일 시키면 다음과 같은 결과물을 보여준다.
[root@sun5.7 /]$ ./thread_test 
Main Thread Start
Main Thread END
Thread Start
Thread:end
		
리눅스에서 처럼 2개의 쓰레드가 동시에(정확히는 동시가 아니지만 이해하기 쉽게)수행 되는게 아니고 메인 쓰레드가 끝날 때까지 쓰레드 생성이 되지 않음을 알 수 있다. 코드에 따라서는 특정 쓰레드가 영원히 실행되지 않는 문제가 발생할 수도 있다. 리눅스에서 개발되는 많은 프로그램들이 다른 유닉스(:12)로도 배포 되는 것을 감안한다면 이는 매우 심각한 문제이다.

솔라리스에서 이러한 문제가 발생하는 이유는 쓰레드라 할지라도 개별적인 프로세스로 실행되는 리눅스와 달리 하나의 LWP를 나눠서 사용하기 때문에 하나의 쓰레드에서 매우 바쁘게 작동할경우 다음 쓰레드 생성을 위한 스케쥴링에 문제가 생기기 때문이다.

작은 정보: 리눅스에서의 쓰레드는 fork()와 유사한 clone()호출을 통한 개별 프로세스로 생성된다. 아직까진(2.4.x) 완전한 쓰레드라고 볼 수 없으며 완전한 쓰레드의 지원은 아마도 커널 2.6.x를 기다려봐야 할것 같다.


3절. 문제 해결

비록 위의 문제가 리눅스에서 발생하진 않지만 많은 리눅스에서 개발되는 프로그램이 솔라리스등의 다른 유닉스로 포팅되고 있다는 것을 감안한다면 반드시 잡아줘야 할 문제다.

문제의 해결방법은 비교적 간단한데, sleep(3)계열의 함수를 이용해서 쓰레드와 쓰레드 사이에 약간의 시간간격을 두어서 쓰레드 스케쥴링을 할 수 있도록 시간을 벌여주면 된다. 다음은 문제를 해결한 코드이다.

  if ((n = pthread_create(&threadid, NULL, threadfunc, NULL)) != 0 )
  {
      perror("Thread create error ");
      exit(0);
  }
  usleep(100);
  printf("Main Thread START\n");
		


4절. 결론

어떻게 보면 팁수준의 매우 간단한 내용인것 같지만 이런 문제일수록 문제의 원인이 애매 모호해서 해결책을 찾기 어려운 경우가 많다. 이런 경우도 마찬가지다. 아마도 pthread:::라이브러리(:12)의 (그리 심각하지 않은?)문제라고 생각되는데 막상 문제가 발생했을 때는 정말 사람을 짜증나게 할 수 있는 문제다.