2012-10-22 9 views
5

Witaj, Jestem nowy w programowaniu wielowątkowym. Próbuję utworzyć kod, który tworzy wątek THREAD1, który po wykonaniu czegoś wyzwala dwa inne wątki, na przykład THREAD2 i THREAD3, a następnie kończy działanie.pthreads: wątek, który wyzwala inne wątki

Napisałem dwa możliwe rozwiązania.

1) Użycie zmiennych warunkowych (nie działa: w niektórych przypadkach dostaję impasu):

pthread_mutex_t ready_mutex = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t ready_cond = PTHREAD_COND_INITIALIZER; 
bool ready = false; 

void* trigger(void*); 
void* func1(void*); 
void* func2(void*); 

int main() 
{ 
    pthread_t thread1; 
    pthread_t thread2; 
    pthread_t thread3; 
    pthread_create(&thread1, 0, &trigger, 0); 
    pthread_create(&thread2, 0, &func1, 0); 
    pthread_create(&thread3, 0, &func2, 0); 
    pthread_join(thread1, 0); 
    pthread_join(thread2, 0); 
    pthread_join(thread3, 0); 
} 

void *trigger(void*) 
{ 
    pthread_mutex_lock(&ready_mutex); 
    ready = true; 
    pthread_cond_broadcast(&ready_cond); 
    pthread_mutex_unlock(&ready_mutex); 
    return 0; 
} 

void *func1(void*) 
{ 
    while (!ready) // Needed to avoid spuriuos wake-up 
    { 
     pthread_mutex_lock(&ready_mutex); 
     pthread_cond_wait(&ready_cond, &ready_mutex); 
     pthread_mutex_unlock(&ready_mutex); 
    } 
    std::cout << "In 'func1'>> Do something" << std::endl; 
    return 0; 
} 

void *func2(void*) 
{ 
    while (!ready) // Needed to avoid spuriuos wake-up 
    { 
     pthread_mutex_lock(&ready_mutex); 
     pthread_cond_wait(&ready_cond, &ready_mutex); 
     pthread_mutex_unlock(&ready_mutex); 
    } 
    std::cout << "In 'func2'>> Do something" << std::endl; 
    return 0; 
} 

2) thread1 bezpośrednio tworzy dwa inne wątki.

pthread_mutex_t ready_mutex = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t ready_cond = PTHREAD_COND_INITIALIZER; 

pthread_t thread1; 
pthread_t thread2; 
pthread_t thread3; 

void* trigger(void*); 
void* func1(void*); 
void* func2(void*); 

int main() 
{ 
    pthread_create(&thread1, 0, &trigger, 0); 

    pthread_join(thread1, 0); 
    pthread_join(thread2, 0); 
    pthread_join(thread3, 0); 
} 

void *trigger(void*) 
{ 
    std::cout << "In 'trigger'>> Do something" << std::endl; 

    pthread_create(&thread2, 0, &func1, 0); 
    pthread_create(&thread3, 0, &func2, 0); 

    return 0; 
} 

void *func1(void*) 
{ 
    std::cout << "In 'func1'>> Do something" << std::endl; 

    return 0; 
} 

void *func2(void*) 
{ 
    std::cout << "In 'func2'>> Do something" << std::endl; 

    return 0; 
} 

chciałbym poznać Twoją opinię. Dziękuję bardzo

+0

Twoja druga implementacja wydaje się działać dobrze, co według ciebie jest z nią nie tak? – engineerC

+0

Twoja druga opcja jest czystsza i ładniejsza. Zrobiłbym to. –

+0

@CaptainMurphy: Zastanawiam się, czy istnieje lepszy sposób osiągnięcia tego celu. Ze strony podręcznika POSIX wydaje mi się, że zmienne warunkowe lepiej pasują do tego celu, ponieważ można je wykorzystać do sygnalizowania określonego zdarzenia. –

Odpowiedz

5

Użycie zmiennych warunkowych (NIE DZIAŁA: w niektórych przypadkach dostaję impasu):

Kod nie zablokować mutex podczas sprawdzania stanu wspólny zmienna ready. Kiedy się zablokuje, muteks ready może się dobrze zmienić w tym czasie, dlatego widzisz zakleszczenia.

Poprawna wersja czekać na zmianę stanu ze zmiennej stan jest (sprawdzanie błędów pominięta):

pthread_mutex_lock(&ready_mutex); 
while(!ready) // Needed to avoid spuriuos wake-up 
    pthread_cond_wait(&ready_cond, &ready_mutex); 
// ready == true here 
pthread_mutex_unlock(&ready_mutex); 

Powyższe zakłada, że ​​ready się kiedykolwiek zmienić tylko wtedy, gdy sama mutex odbywa.

+0

Tak, masz rację. Powracając do mojego pytania, czy powinienem użyć zmiennych warunkowych (rozwiązanie nr 1) lub odroczonego tworzenia wątku (rozwiązanie nr 2)? –

+1

@ seg.fault Używałbym brzytwy Ockhama (http://en.wikipedia.org/wiki/Occam's_razor): biorąc pod uwagę wiele rozwiązań problemu, wybierz prostsze. –

Powiązane problemy