2012-07-13 2 views
4

최근에 시작된 자식 스레드와 마스터 스레드를 동기화하는 데 문제가 있습니다.시작 스레드가 초기화 코드를 실행하기를 기다리는 방법

내가하고 싶은 것입니다 :

  • 마스터 스레드가 자식 스레드가 초기화되면
  • (시간이 걸릴 수 있습니다) 새 자식 스레드 블록
  • 자식 스레드가 시작되고이 초기화를 만들고, 메인 스레드는 계속 (그리고 두 개의 스레드가 병렬로 실행)

내 첫 번째 시도는 같은했다 :

typedef struct threaddata_ { 
    int running; 
    } threaddata_t; 

    void*child_thread(void*arg) { 
    threaddata_t*x=(threaddata_t)arg; 
    /* ... INITIALIZE ... */ 
    x->running=1; /* signal that we are running */ 

    /* CHILD THREAD BODY */ 

    return 0; 
    } 

    void start_thread(void) { 
    threaddata_t*x=(threaddata_t*)malloc(sizeof(threaddata_t)); 
    x->running=0; 
    int result=pthread_create(&threadid, 0, child_thread, &running); 
    while(!x->running) usleep(100); /* wait till child is initialized */ 

    /* MAIN THREAD BODY */ 
    } 

이제 주간 스레드가 필요 이상으로 긴 시간 동안 잠자기 상태가되기 때문에 전혀 마음에 들지 않았습니다. 그래서 나는이 경쟁 조건을 포함, 내가 발견 할 때까지,이 (적절한 신호를 사용하기보다는 내 자신의 대기 루프 롤링) 첫 번째 시도보다 더 제정신 보였다 뮤텍스를 & 조건

typedef struct threaddata_ { 
    pthread_mutex_t x_mutex; 
    pthread_cond_t x_cond; 
    } threaddata_t; 

    void*child_thread(void*arg) { 
    threaddata_t*x=(threaddata_t)arg; 
    /* ... INITIALIZE ... */ 

    pthread_cond_signal(&x->x_cond); /* signal that we are running */ 

    /* CHILD THREAD BODY */ 

    return 0; 
    } 

    void start_thread(void) { 
    threaddata_t*x=(threaddata_t*)malloc(sizeof(threaddata_t)); 
    pthread_mutex_init(&x->x_mutex, 0); 
    pthread_cond_init (&x->x_cond , 0); 

    pthread_mutex_lock(&x->x_mutex); 
    int result=pthread_create(&threadid, 0, child_thread, &running); 
    if(!result)pthread_cond_wait(&x->x_cond, &x->x_mutex); 
    pthread_mutex_unlock(&x->x_mutex); 

    /* MAIN THREAD BODY */ 
    } 

를 사용하여 2 차 시도를했다 : 하위 스레드가 초기화를 충분히 빨리 완료하면 (주 스레드가 조건을 대기하기 전에) 기본 스레드가 교착 상태가됩니다.

내 경우는별로 드문 일이 아니므로 정말 쉬운 해결책이 있어야하지만 지금은 볼 수 없습니다.

답변

7

적절한 방법 :

bool initialised = false; 
mutex mt; 
convar cv; 

void *thread_proc(void *) 
{ 
    ... 
    mt.lock(); 
    initialised = true; 
    cv.signal(); 
    mt.unlock(); 
} 

int main() 
{ 
    ... 
    mt.lock(); 
    while(!initialised) cv.wait(mt); 
    mt.unlock(); 
} 

이 알고리즘은 가능한 모든 종족을 방지 할 수 있습니다. 뮤텍스가 잠길 때 수정 된 복잡한 조건을 사용할 수 있습니다 (단순한! 초기화 된 대신).

+0

+1 :'while()'루프에 대해 가짜 웨이크 업 (wake-ups)에 대한 보호를 추가하는데도 사용됩니다. – alk

+0

이것은 OP의 두 가지 접근 방식의 조합 (첫 번째 접근 방식에서'usleep()'이'pthread_cond_wait()'로 대체 됨)와 정확히 같습니다. – caf

+0

첫 번째 접근 방식에서 플래그를 실행하는 것은 뮤텍스에 의해 보호되지 않는다는 점에 유의하십시오. –

2

올바른 도구는 sem_t입니다. main 스레드는 0으로 스레드를 초기화하고 새로 시작된 스레드에서 토큰을 수신 할 때까지 대기합니다.

자식 스레드가 뮤텍스를 잠그지 않았으므로 뮤텍스/조건 솔루션에 경쟁 조건이 있습니다. condvar/뮤텍스 쌍 사용의

+0

나는 mutexes를 조사 할 것이다. 그러나 게시 후 나는 또한 race-condition에 대한 원인을 알아 차렸다. 내가 pthread_create를 호출하기 전에 잠긴) 내 mutex의 잠금/잠금 해제로 pthread_cond_signal()에 대한 호출을 묶는 것으로 충분하다는 것을 올바르게 이해합니까? 나는 그것이해야한다고 생각하고 "while (초기화 된) wait()"루프가 @ dmitry-poroh에 의해 제안 된 것과 같을 것 같아요. –

+0

sem_t가 pthreads의 일부 w32 구현에서 사용 가능하지 않은 것으로 보입니다. 사용하기로 결심했다.)이 코드는 w32를 포함하여 다양한 시스템에서 실행될 예정입니다. w32는 그 솔루션을 거의 제외하지만 실제로는 가장 우아한 솔루션입니다. –

+0

예, 스레드를 시작하기 전에 뮤텍스를 사용하므로 스레드는 기본 스레드가 대기 상태에있을 때만 뮤텍스를 잠글 수 있습니다. 안타깝게도 pthread 구현체에는'sem_t '가 없다. –

2

장벽을 극복해야합니다. 주석에서 Win32에 대한 지원의 필요성에 대해 언급 했으므로 장벽은 최신 Win32 pthreads에서 지원되므로 Win32와 * nix 간의 이식성을 얻기 위해 자체 래퍼를 작성할 필요가 없습니다. 같은

뭔가 :

typedef struct threaddata_ { 
    pthread_barrier_t* pbarrier; 
} threaddata_t; 

void* child_thread(void*arg) { 
    threaddata_t*x=(threaddata_t*)arg; 
    /* ... INITIALIZE ... */ 

    int result = pthread_barrier_wait(x->pbarrier); 

    /* CHILD THREAD BODY */ 

    return 0; 
} 

void start_thread(void) { 
    pthread_barrier_t barrier; 
    int result = pthread_barrier_init(&barrier, NULL, 2); 

    threaddata_t*x=(threaddata_t*)malloc(sizeof(threaddata_t)); 
    x->pbarrier = &barrier; 

    int result=pthread_create(&threadid, 0, child_thread, &x); 

    result = pthread_barrier_wait(&barrier); 
    /* child has reached the barrier */ 

    pthread_barrier_destroy(&barrier); /* note: the child thread should not use */ 
             /* the barrier pointer after it returns from*/ 
             /* pthread_barrier_wait()     */ 


    /* MAIN THREAD BODY */ 
} 

이 솔루션의 단점은 그것이 수도 불필요하게 차단 자식 스레드 순간적이다. 문제가있는 경우 condition variable solution mentioned by Dmitry Poroh을 사용하는 것이 좋습니다.

관련 문제