2012-08-11 3 views
1

이 pthreads에 익숙하지 않습니다. 숫자를 무작위로 표시하는 대신 순서대로 표시해야하는 프로그램을 작성했습니다. 나는 pthrea_join() 방법을 사용했다.pthread가 순차적으로 실행되지 않습니다.

int cnt=0,i=1; 
pthread_t th[10]; 
int printmsg() 
{ 
    cnt++; 
    printf("thread no. %d\n",cnt); 
} 
void tosync() 
{ 
    if(i>0) 
    pthread_join(th[i-1],NULL); // <---here i am blocking the previous thread..       
    printmsg(); 
} 
void main(void) 
{ 
    pthread_create(&th[0], NULL,(void*)&tosync, NULL); 
    for(i=1;i<10; i++){ 
    pthread_create(&th[i],NULL, (void*) &tosync, NULL); 
    } 
    int y; 
    for(int i=0; i<10; i++) 
    pthread_join(th[i],NULL); 
    return; 
} 

아직도 난 ... 무작위로 번호 plzz을 얻고 다음과 같이 프로그램입니다. help

+1

전역 변수'i'에 액세스 할 때 문제가있는 것 같습니다. 주 스레드 (증가)뿐만 아니라 작업 스레드에서. 그 외에는 무엇을 기대합니까? 스스로 기다려? – Xyand

+0

죄송합니다. 편집하는 것을 잊어 버렸습니다 ... 지금도 숫자가 무작위로 나타납니다. – nitish712

답변

1

pthread_join (th [i-1], NULL)이 줄에는 몇 가지 문제점이 있습니다. 스레드를 만들면 i의 값이 증가합니다. 첫 번째 세 스레드 OS 스위치 thrid 스레드 시작을 만들고 OS 스레드가 나머지 스레드를 만드는 주 스레드로 전환한다고 가정합니다. 모든 스레드를 만든 후 i의 값은 10/ 입니다. 이제 OS가 thrid 스레드로 전환한다고 가정하고 10-1 = 9 번째 스레드가 끝나기를 기다리고 similary가 계속됩니다. 궁극적으로 항상 무작위로 인쇄됩니다. 당신의 전략은 잘못되었습니다.

문제가 당신이 toSync 기능이 실행될 때 무슨 값 i 모르겠입니다, 당신은 i 값을 사용하는 toSync 기능이

int cnt=0,i=1; 
pthread_t th[10]; 
int printmsg() 
{ 
cnt++; 
printf(thread no. %d\n",cnt); 
} 
void tosync() 
{ 

printmsg(); 
} 
void main(void) 
{ 
pthread_create(&th[0], NULL,(void*)&tosync, NULL); 
for(i=1;i<10; i++){ 
pthread_create(&th[i],NULL, (void*) &tosync, NULL); 
pthread_join(th[i],NULL); // <---here i am blocking the previous thread.. 
} 

return; 
} 
1

을 시도합니다.

극단적 인 경우 모든 스레드에 대해 값 10을 가질 수 있습니다. 생성 된 스레드가 실행되기 전에 스레드를 만드는 루프가 실행되면 발생합니다.

깨끗한 해결책은 pthread_createi 값을 전달하고 i 대신 toSync을 사용하는 것이 가장 좋습니다. 예 : 에 대해

int *id = (int*)malloc(sizeof(int)); 
*id = i; 
pthread_create(&th[i],NULL, (void*) &tosync, id); 

다른 일들이 생각하는 : 그것은

  • 기다리는 어떤 전임자를 가지고 있지 않기 때문에

    1. toSync이 ID를 0으로 스레드에 대한 특별한 처리가 필요 main의 마지막 루프 안 그들이 이미 조인되었으므로 스레드 0-8에 pthread_join을 호출합니다. 동일한 스레드에서 pthread_join 여러 번 호출의 결과는 무엇 일어나고있는 것은 스레드가 실제로 시작되었을 때 당신의 tosync() 방법은 전역 변수 i 대신 i의 가치를 아는을 사용한다는 것입니다 undefined
  • +1

    'malloc'을 사용하면 메모리와 CPU 시간이 많이 낭비됩니다. 'i'를 주소를 취하는 것보다'void *'로 단순히 캐스팅하고 스레드 시작 함수에서'int'로 다시 캐스트하십시오. –

    +0

    @R .. 아, 좋은 지적이야! – johlo

    +0

    또한 동기화가 낭비된다는 점에주의하십시오. 하나의 스레드에서'malloc'을 호출하고 다른 스레드에서'free'를 호출하면 메모리를 가져 와서 재사용을 위해 빈 풀로 반환하는 숨겨진 동기화 비용이 항상 발생합니다. –

    1

    입니다. i (또는 이전 pthread_t에 대한 포인터)을 tosync에 전달하여 실제로 어떤 스레드와 합류해야하는지 기억하려면 pthread_create를 통해 전달해야합니다.

    void* tosync(void* ptr) 
    { 
        pthread_t* threadIndex = (pthread_t*)ptr; 
        if(threadIndex != NULL) 
         pthread_join(*threadIndex, NULL); // <---here i am blocking the previous thread..       
        printmsg(); 
    } 
    
    ...in the loop... 
    
    pthread_create(&th[i], NULL, tosync, &th[i-1]); 
    

    그것은 그가 당신의 방법에 threadIndex로 전달됩니다 앞서 pthread_create 즉 인덱스를 포함하는 경우, 각 스레드가 별도의 인덱스를 알 마지막 매개 변수입니다.

    +0

    니스, 첫 번째 스레드에주의를 기울여야하기 때문에'pthread_create' 호출과'tosync'는 반드시 몇 가지 조건을 포함해야합니다. –

    +0

    @JensGustedt 좋은 지적. 그것은 NULL을 검사하고 첫 번째 스레드가 NULL을 매개 변수로 계속 전달하도록합니다. 코드를 수정했습니다 :) –

    +0

    @Isaksson 지금 나는 잘못 가고있는 것이 분명합니다 ... 고맙습니다. :) – nitish712

    1

    또 다른 방법 : 각 스레드가가 대기해야하는 스레드를 알 수 있도록

    #include <stdio.h> 
    #include <pthread.h> 
    
    struct threadData{ 
        int id; 
        pthread_t prev; 
    }; 
    
    
    void tosync(void *data) 
    { 
        struct threadData *td=data; 
        if ((*td).prev!=0){ 
         printf("%i waiting\n",(*td).id); 
         fflush(0); 
         pthread_join((*td).prev,NULL); // <---here i am blocking the previous thread..       
        } 
        printf("%i runnning\n",(*td).id); 
        fflush(0); 
        free(td); 
    } 
    
    int main(void) 
    { 
        int i; 
        struct threadData *td; 
        pthread_t nextThreadID=0; 
        for(i=0;i<10; i++){ 
         td=malloc(sizeof(struct threadData)); 
         (*td).prev=nextThreadID; 
         (*td).id=i; 
         pthread_create(&nextThreadID,NULL, (void*) &tosync, (void *)td); 
        } 
        pthread_join(nextThreadID,NULL); 
        return 0; 
    } 
    
    2

    당신은 당신의 tosync 일상에 뭔가를 전달해야합니다. 또한 첫 번째 스레드는 다른 사람을 기다리지 않아야합니다.스레드 시작 루틴에 적절한 서명을 사용하면 인수를 전달할 수 있습니다.

    void * tosync(void *arg) 
    { 
        pthread_t *me = (pthread_t *)arg; 
        if (me > th) pthread_join(me[-1],NULL); 
        printmsg(); 
        return 0; 
    } 
    

    main

    int를 반환해야합니다. 시작 루틴에 더 이상 캐스트가 필요 없기 때문에 루프가 단순 해졌습니다. 각 스레드는 이미 이전 버전과 결합하고 있으므로 main 스레드는 마지막 스레드와 만 조인하면됩니다.

    int main(void) 
    { 
        for(i=0;i<10; i++){ 
        pthread_create(&th[i],NULL, tosync, &th[i]); 
        } 
        pthread_join(th[9],NULL); 
        return 0; 
    } 
    
    관련 문제