Pthread 동기화에 대한 질문-보충설명입니다.
#define _REENTRANT /* basic 3-lines for threads */
#include
#include
#include
void *odd(void *); /* thread routine */
void *even(void *); /* thread routine */
int
main(int argc, char *argv[] )
{
int i, *ip;
int count;
thread_t *tid; /* array of thread IDs */
if (argc != 2) {
printf("Usaget_thread_r [count]\n");
return (1);
}
if((count = atoi(argv[1])) == 0)
{
puts("argv[1] is 0 or Input Error\n");
return(0);
}
if((tid = (thread_t *) malloc(sizeof(thread_t)*count)) == NULL)
{
perror("malloc error");
exit(1);
}
for ( i = 0; i < count ; i++)
{
ip = (int *)malloc(sizeof(int));
*ip = i;
if(i%2)
pthread_create(&tid[i], NULL, odd, (void *)ip);
else
pthread_create(&tid[i], NULL, even, (void *)ip);
/**********************************************************/
// printf("this is i %d\n", i);
/***********************************************************/
}
for ( i = 0; i < count; i++)
pthread_join(tid[i], NULL);
printf("main() reporting that all %d threads have terminated\n",
i);
free(tid);
return (0);
} /* main */
void *
odd(void *arg)
{
int print_num = *((int *)arg);
free(arg);
printf("oddthread %d count %d\n", thr_self(), print_num);
return (NULL);
}
void *
even(void *arg)
{
int print_num = *((int *)arg);
free(arg);
printf("eventhread %d count %d\n", thr_self(), print_num);
return (NULL);
}
두분의 답변을 지켜본 결과 even 0 -> print 0 -> odd 1 -> print 1..
이런식의 순차적인 실행은 무의미하다고 봅니다.
그래서 제가 원하는 것은 even0 -> odd 1 -> even 2 -> odd 3 -> enve 4
-> odd 5...이런식으로 실행이 되었음 하는 것입니다.
그런데 오해하지 마셔야 할 것은 이러한 순서에서 even 0이 끝나고 나서
야 비로서 odd 1이 시작된다는 것이 아니라는 것입니다.
즉 종료는 비순서적으로 될 수 있지만 원칙적으로 시작만큼은 0->1->2
->3..과 같이 해야 한다는 뜻입니다.
만약 이렇게 질문을 바뀌더라도 결국 한가지 의문은 남습니다.
0->1->2->3의 순서로 시작(실행이나 종료가 아님!)되었던 thread들이 for
문에 printf를 넣는 순간 순서가 엉켜버렸는지...심지어는 실행조차 되지
않는 thread가 생기는 것은 왜 그런 것일까요?
이 부분에 대한 명확한 답변이 있다면 참 좋겠습니다.
그럼 프로그램 고수들의 현명한 답변을 기대하겠습니다.
Re: Pthread 동기화에 대한 질문입니다.
접근 방식에서부터 문제가 있네요.
이것은 thread의 Test라기 보다는 함수의 Test에 가깝군요.
왜냐하면,
; for ( i = 0; i < count ; i++)
; {
; ip = (int *)malloc(sizeof(int));
; *ip = i;
; if(i%2)
; pthread_create(&tid[i], NULL, odd, (void *)ip);
; else
; pthread_create(&tid[i], NULL, even, (void *)ip);
;/********************************************************/
;// printf("this is i %d\n", i);
;/********************************************************/
; }
이렇게 call할려면 function을 Call하는게 훨씬 유리하죠.
뭐하게 어렵게 thread들을 만들죠 !
여기에 무슨 동기화가 필요한지 ?!
이와같은 상황은 os에 따라, 작업시점에 따라 결과들이
완전히 상이하게 나오게 됩니다.
그게 아니구요...
사실은 이 프로그램은 가장 기본적인 동작을 수행하는 그야말로 Thread가
필요 없는 Program이 맞습니다.
하지만.
이 프로그램은 일종의 모형 프로그램으로 지금은 단순하게 print만하는
even, odd프로그램이 나중에는 굉장히 할일이 많은 진짜 프로그램으로
대체될 것입니다.
그러므로...
지금 답변은 님이 약간의 오해를 하신것으로 생각하시고 제가 처음에 질
문했던 부분에 대한 답변을 해주시면 어떨까요?
Re^3: 그게 아니구요...
안녕하세요 ^^;
앞에 다른 님께서 답변을 했듯이 현재 님의 코드에는 동기화에 대한 부분
이 고려되어 있지 않습니다. 또한 님께서 지적하셨듯이 이런 코드라면 쓰
레드를 쓸 필요가 없죠.
나중에 어떤 대단한 일이 들어갈거라고 했습니다만 1이 다 끝난 다음에 2
가 그 다음에 3이 이런 식이라면 쓰레드를 썼을때 메리트가 없습니다. 결
국 순서대로 흐르는 코드가 된다면 쓰레드 생성 및 컨텍스트 스위치의 부
담만 지게 될 뿐입니다. 물론 프로세스보다는 덜 하겠지만요.
쓰레드를 쓰고자 하신다면 순서에 상관없이 돌도록 해야 더 좋겠죠. 그리
고 그 순서라는 것이 커널에서 정하는 마음대로이기 때문에 더욱 그러합니
다. 만약 억지로 순서대로 맞추고자 한다면 쓰레드간에 공유할 수 있는 구
조체나 변수를 유지하고 쓰레드에도 생기는 순서대로 아이디를 부여합니
다. 그리고 쓰레드가 실행되는 대로 전역 변수나 구조체의 값을 작업이 끝
난 쓰레드의 번호로 셋팅을 합니다. 뭐 이런식으로 굳이 구현을 하자면
할 수도 있겠죠. ^^; 아 이것은 어디까지나 저의 무식한 머리에서 나온 해
이니 다른 분이 더 적절한 해를 제시해줄 수도 있습니다.
일단 제가 생각한 해법대로 구현을 한다고 하면 그건 결국 순서대로 실행
하는 것보다 더 느려질 수 밖에 없습니다. 또한 쓰레드 옵션을 확인해보
지 않았습니다만 옵션에 실시간 스케쥴링이 아닌 옵션으로 쓰레드가 시작
하게 된다면 아무래도 장담할 수 없겠죠.
그럼 즐거운 시간 보내시기 바랍니다. ~
Re^3: 그게 아니구요...
아마 이런 코드를 원하시는 듯 한데요.
열심해 해보세요.
test는 sun에서 했습니다.
cc -o file file.c -lthread
#define _REENTRANT /* basic 3-lines for threads */
#include
#include
#include
typedef struct _taskInfo {
int *iv;
int *max;
int idx;
int exit;
int work;
}taskInfo;
mutex_t prCtl[2];
void *task_s(void *);
int main(int argc, char *argv[])
{
int k, inc=0, count;
thread_t tid[2];
taskInfo ti[2] = {{&inc, &count, 0, 0, 0}, {&inc, &count, 1, 0,
0}};
if (argc != 2) {
printf("Usaget_thread_r [count]\n");
return (1);
}
if((count = atoi(argv[1])) == 0) {
puts("argv[1] is 0 or Input Error\n");
return(0);
}
for(k = 0; k < 2; k++) {
mutex_init(&prCtl[k], USYNC_PROCESS, 0);
mutex_lock(&prCtl[k]);
pthread_create(&tid[k], NULL, task_s, (void *)&ti[k]);
}
for(inc = 0; inc < count; inc++) {
ti[inc%2].work = 0;
mutex_unlock(&prCtl[inc%2]);
for( ; ti[inc%2].work <= 0; ) usleep(1);
}
ti[0].exit = 1;
ti[1].exit = 1;
for ( k = 0; k < count; k++)
pthread_join(tid[k], NULL);
printf("main() reporting that all %d threads have terminated\n",
inc);
return (0);
}
void *
task_s(void *arg)
{
int k, old = -1;
taskInfo *ti = (taskInfo *)arg;
char label[2][10] = {"even", "odd "};
for( ; ; ) {
mutex_lock(&prCtl[ti->idx]);
if(old != *(ti->iv)) {
old = *(ti->iv);
if((*(ti->iv) % 2) == ti->idx)
printf("%sthread %d count %d\n", label[ti->idx],
thr_self(), *(ti->iv));
if(ti->exit) break;
}
ti->work = 1;
mutex_unlock(&prCtl[ti->idx]);
}
return (NULL);
}
댓글 달기