Attualmente sto lavorando su un problema che simula un modello esteso di Producer-Worker. In questo problema ci sono 3 lavoratori e 3 strumenti disponibili, e per i lavoratori al lavoro hanno bisogno di 2 strumenti (e materiali, ma quelli sono irrilevanti). Se ci sono> = 2 strumenti nel vault, un lavoratore prenderà 2. Altrimenti, essi aspetteranno una variabile di condizione che verrà segnalata quando ci sono> = 2.C++ 11 Thread: thread multipli in attesa di una variabile di condizione
Questo va bene con 2 lavoratori: uno funzionerà, quindi restituirà gli strumenti al vault e l'altro lavoratore in attesa verrà risvegliato e prenderà 2 strumenti. Il problema è che, con 3 lavoratori, ci sarà sempre uno affamato per ottenere gli strumenti.
Dopo alcuni test, ho notato che i thread in attesa di una variabile di condizione sono strutturati in pila. C'è comunque la possibilità di farlo in coda? (1 attende, 2 attende e 3 attende. Quando 1 è risvegliato e vuole fare un altro, deve attendere dietro 2 e 3.)
Ecco un esempio di output. Il codice è troppo lungo, quindi lo posterò se è davvero necessario. Esistono 3 thread di lavoro e 1 mutex di strumenti. Chi sta morendo di fame si differenzia a vicenda.
1 Tools taken. Remaining: 1
2 Waiting on tools...
3 Waiting on tools...
1 Operator Product made. Tools returned. Tools now:3
3 Tools taken. Remaining: 1
1 Waiting on tools...
3 Materials returned for switch.
3 Operator Product made. Tools returned. Tools now:3
1 Tools taken. Remaining: 1
3 Waiting on tools...
1 Materials returned for switch.
1 Operator Product made. Tools returned. Tools now:3
3 Tools taken. Remaining: 1
1 Waiting on tools...
3 Materials returned for switch.
3 Operator Product made. Tools returned. Tools now:3
1 Tools taken. Remaining: 1
3 Waiting on tools...
1 Materials returned for switch.
1 Operator Product made. Tools returned. Tools now:3
3 Tools taken. Remaining: 1
1 Waiting on tools...
3 Materials returned for switch.
3 Operator Product made. Tools returned. Tools now:3
1 Tools taken. Remaining: 1
3 Waiting on tools...
1 Materials returned for switch.
...
(Come si può vedere 2 non viene mai gli strumenti ...)
Aggiornamento: 2013/07/05 ho aggiunto un certo codice.
int tools = 3; //global
string last; //current last product on output buffer
mutex toolsMutex;
mutex matSearchMutex;
int main(){
//Initializing Producers
Producer prod1(1);
Producer prod2(2);
Producer prod3(3);
thread p1(processor,1);
thread p2(processor,2);
thread p3(processor,3);
p1.detach();
p2.detach();
p3.detach();
while(true){//forever running
}
return 0;
}
Processore:
//Processor method
void processor(int i){
srand(time(NULL));
while (true){ //forever running
bool hasTools = false;
bool productMade = false;
while (productMade == false){ //while product has yet to be made.
//choose what to make...
if (hasTools == false){
thread matT(getMaterials,whatToMake);
thread toolT(getTools,i);
toolT.join();
matT.join();
hasTools = true;
}
else{ //tools acquired but no materials
thread matT(getMaterials,whatToMake);
matT.join();
}
if (recordedLast.compare(last) != 0){
//return materials and acquire new ones the next run
continue;
}
else {
makeProduct(whatToMake);
unique_lock<mutex> locker(toolMutex);
tools = tools + 2;
cout << i << " Operator Product made. Tools returned. Tools now:" << tools << endl;
productMade = true;
if (tools >=2) toolsCV.notify_one();
}
//done processing
}
}
}
makeProducts:
void makeProduct(int i){
unique_lock<mutex> mainMatLock(matSearchMutex);
// make product according to i
this_thread::sleep_for(chrono::milliseconds(rand() % 1000 + 10));
}
getTools:
void getTools(int i){
unique_lock<mutex> locker(toolMutex);
if (tools <2){
cout << i << " Waiting on tools..." << endl;
toolsCV.wait(locker);}
tools = tools - 2;//tools acquired
cout << i <<" Tools taken. Remaining: " << tools << endl;
}
grazie a coloro che hanno risposto. Proverò a implementare una coda di attesa stasera utilizzando più variabili di condizione.
(PS C'è qualche modo migliore per fare formattazione del codice qui su Stack Overflow? Altro che i quattro spazi ...
Perché non pubblichi il tuo codice attuale? Hai provato a trasmettere sulla variabile di condizione (rispetto al segnale)? Non hai specificato nulla riguardo al tuo ambiente, ma potresti voler guardare su http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_08_04_01 –
_ "C'è un modo migliore per fare il codice? formattazione qui su Stack Overflow? "_ Immettere il codice senza spazi, quindi evidenziare l'intero blocco di codice e premere Ctrl-K o premere il tasto ** {} ** sulla barra degli strumenti sopra la casella di modifica –