2009-08-10 15 views
12

Sto usando boost::mutex::scoped_lock in questo modo:Perché Boost scoped_lock non sblocca il mutex?

void ClassName::FunctionName() 
{ 
    { 
    boost::mutex::scoped_lock scopedLock(mutex_); 
    //do stuff 
     waitBoolean=true; 
    } 
    while(waitBoolean == true){ 
     sleep(1); 
    } 
    //get on with the thread's activities 
} 

Fondamentalmente imposta waitBoolean, e gli altri segnali di filo che viene fatto impostando waitBoolean false;

Questo non sembra funzionare, tuttavia, perché l'altro thread non può ottenere un blocco su mutex_ !!

Stavo partendo dal presupposto che avvolgendo il campo scoped_lock tra parentesi avrei chiuso il suo blocco. Questo non è il caso? La lettura online dice che rinuncia al mutex solo quando viene chiamato il distruttore. Non verrà distrutto quando uscirà dall'ambito locale?

Segnalazione parte di codice:

while(running_){ 
    boost::mutex::scoped_lock scopedLock(mutex_); 
    //Run some function that need to be done... 
    if(waitBoolean){ 
     waitBoolean=false; 
    } 
} 

Grazie!

+1

L'oggetto scoped_lock viene distrutto nella parentesi di chiusura e il mutex viene rilasciato. Per favore, pubblica la parte di segnalazione del codice. A proposito, un boost :: condition_variable è migliore per le tue esigenze – neuro

+0

Ben visto il tuo codice di segnalazione può funzionare in certi casi, ma dipende dall'elaborazione che fai (i tuoi commenti). Se c'è un altro synchro è peggio. Una variabile di condizione è il modo per farlo. Ho pubblicato il codice che uso per fare questo tipo di sincronizzazione. – neuro

+0

Il "lavoro" del thread di segnalazione non blocca qualcos'altro. Funziona in modo indipendente. – Alex

risposta

16

Il campo scoped_lock deve essere effettivamente rilasciato alla fine dell'ambito. Tuttavia non blocchi il waitBoolean quando lo stai eseguendo, suggerendo di non proteggerlo correttamente anche in altri posti - ad es. dove è impostato su false e finirai con cattive condizioni di gara.

Direi che dovresti usare un boost :: condition_variable per fare questo genere di cose, invece del controllo sleep + thread-safe.

22

Per sincronizzare due thread utilizzare una variabile di condizione. Questo è lo stato del modo dell'arte per sincronizzare due thread nel modo desiderato:

Utilizzando spinta, la parte in attesa è qualcosa di simile:

void BoostSynchronisationPoint::waitSynchronisation() 
{ 
    boost::unique_lock<boost::mutex> lock(_mutex); 

    _synchronisationSent = false; 
    while(!_synchronisationSent) 
    { 
     _condition.wait(lock); // unlock and wait 
    } 
} 

Notifica parte è qualcosa di simile:

void BoostSynchronisationPoint::sendSynchronisation() 
{ 
    { 
     boost::lock_guard<boost::mutex> lock(_mutex); 
     _synchronisationSent = true; 
    } 

    _condition.notify_all(); 
} 

Il business con _synchronisationSent è quello di evitare wakeups spurie: vedi wikipedia

0

Inoltre vorrei suggerire di contrassegnare come volatile che waitBo Olean, comunque devi usare una condizione o anche meglio una barriera.

Problemi correlati