2012-10-22 15 views
5

Ciao, Sono nuovo alla programmazione multi-thread. Sto provando a creare un codice che crea un thread THREAD1, che, dopo aver eseguito qualcosa, attiva altri due thread, ad esempio THREAD2 e THREAD3, quindi esce.pthreads: un thread che attiva altri thread

Ho scritto due possibili soluzioni.

1) L'utilizzo di variabili di condizione (NON FUNZIONA: in alcuni casi ho una situazione di stallo):

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 crea direttamente gli altri due fili.

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; 
} 

mi piacerebbe conoscere la vostra opinione. La ringrazio molto

+0

La tua seconda implementazione sembra funzionare correttamente, cosa pensi che sia sbagliato in questo? – engineerC

+0

La tua seconda opzione è più pulita e più bella. Lo farei. –

+0

@CaptainMurphy: Mi chiedo solo se esiste un modo migliore per raggiungere questo obiettivo. Dalle pagine di manuale POSIX, mi sembra che le variabili di condizione siano più adatte a questo scopo poiché possono essere utilizzate per segnalare un evento particolare. –

risposta

5

L'utilizzo di variabili di condizione (non funziona: in alcuni casi ho una situazione di stallo):

Il codice non si blocca il mutex quando si controlla lo stato di condivisione variabile ready. Quando blocca il mutex ready potrebbe essere cambiato molto da quel momento, questo è il motivo per cui si vedono deadlock.

La versione corretta di aspettare per il cambiamento di stato di una variabile di condizione è (controllo degli errori omesso):

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); 

Quanto sopra presuppone che ready è mai cambiato solo quando si svolge la stessa mutex.

+0

Sì, hai ragione. Quindi, tornando alla mia domanda, dovrei usare le variabili di condizione (soluzione n. 1) o la creazione di thread posticipato (soluzione n. 2)? –

+1

@ seg.fault Userei [il rasoio di Occam] (http://en.wikipedia.org/wiki/Occam's_razor): date più soluzioni per un problema sceglierne una più semplice. –

Problemi correlati