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가 생기는 것은 왜 그런 것일까요?

이 부분에 대한 명확한 답변이 있다면 참 좋겠습니다.

그럼 프로그램 고수들의 현명한 답변을 기대하겠습니다.

익명 사용자의 이미지

접근 방식에서부터 문제가 있네요.

이것은 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프로그램이 나중에는 굉장히 할일이 많은 진짜 프로그램으로
대체될 것입니다.

그러므로...

지금 답변은 님이 약간의 오해를 하신것으로 생각하시고 제가 처음에 질
문했던 부분에 대한 답변을 해주시면 어떨까요?

익명 사용자의 이미지

안녕하세요 ^^;

앞에 다른 님께서 답변을 했듯이 현재 님의 코드에는 동기화에 대한 부분
이 고려되어 있지 않습니다. 또한 님께서 지적하셨듯이 이런 코드라면 쓰
레드를 쓸 필요가 없죠.

나중에 어떤 대단한 일이 들어갈거라고 했습니다만 1이 다 끝난 다음에 2
가 그 다음에 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);
}

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.