|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Bannato
Iscritto dal: Feb 2013
Messaggi: 1552
|
C++11 Thread esempietto banale con domanda
Questo semplice codice lancia 100 thread e aspetta che finiscano.
Codice:
#include <thread> using namespace std; int duratathread=100; int numerothreads=100; int completati=0; void miothread() { for (int contatore=0; contatore<duratathread; contatore++) { } completati+=1; } int main() { for (int contatore=0; contatore<numerothreads; contatore++) { new thread(miothread); } while (completati<numerothreads) { this_thread::sleep_for(chrono::milliseconds(100)); }; } ossia se commento "this_thread::sleep_for(chrono::milliseconds(100));", non esce dal programma. Chi mi puo' aiutare per favore? |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Jul 2008
Città: Roma
Messaggi: 542
|
Probabilmente perché così il thread principale occupa il 100% del tempo CPU facendo in modo che gli altri thread restino sospesi
|
![]() |
![]() |
![]() |
#3 |
Bannato
Iscritto dal: Feb 2013
Messaggi: 1552
|
Si', grazie, chiaramente quello che dici tu suona bene.
Pero' credevo che i thread avessero tutti la stessa priorità, e non che il principale l'avesse piu' elevata. Sbaglio? |
![]() |
![]() |
![]() |
#4 |
Bannato
Iscritto dal: Feb 2013
Messaggi: 1552
|
Ho trovato l'interessantissima risposta!
Devo dichiararare completati come VOLATILE http://stackoverflow.com/questions/4...e-keyword-in-c |
![]() |
![]() |
![]() |
#5 |
Bannato
Iscritto dal: Feb 2013
Messaggi: 1552
|
|
![]() |
![]() |
![]() |
#6 | |
Senior Member
Iscritto dal: May 2001
Messaggi: 12849
|
Quote:
Una variabile di tipo volatile costringe il compilatore a generare codice che accede in memoria ogni qual volta si accede a quella variabile, dunque il ciclo non viene buttato via, perché non può fare assunzioni sul valore della variabile. E' ordinaria amministrazione quando si lavora con le ottimizzazioni abilitate. E considera che la situazione si complica se consideri che per questioni di efficienza: a) il compilatore può riordinare le istruzioni b) il processore può riordinare le istruzioni (architetture out-of-order) Il che deve portare il programmatore a stare molto attento, specie nella programmazione multithreaded lock-free. Buon divertimento ![]() |
|
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Jul 2011
Messaggi: 381
|
Dal mio punto di vista non è (solo) una questione di ottimizzazione quanto invece un problema di sezione critica.
Tu hai 100 thread che vanno a scrivere contemporaneamente su una variabile condivisa quindi nel momento in cui vanno a scriverla molto probabilmente sarà in uno stato inconsistente nel momento della scrittura. Inoltre hai il main principale che la legge di continuo e neanche in questo caso sai se è in uno stato consistente. Quindi in soldoni hai un programma che non è deterministico. Mi spiego meglio, supponi che hai 2 threads A e B che devono eseguire l'operazione completati+=1; nessuno ti garantisce che tale operazione sia atomica (da qui vedi ottimizzazione del compilatore) infatti tale operazione potresti averla in ASM così: Codice:
#Supponiamo che in EAX ci sia il dato da incrementare e lo sposto su EBX MOV %EAX, %EBX #Incremento EBX INC %EBX #Metto il risultato in EAX MOV %EBX, %EAX Ora ipotizza che parte il thread A ed esegue la prima MOV, arriva un interrupt e successivamente parte il thread B che esegue tutto il codice quindi va a riscrivere in EAX il valore "8" e poi riparte il thread A che anch'esso va a riscrivere "8" in %EAX. Come vedi il risultato di 2 threads è sbagliato. Il fatto è che tu non sai come il compilatore ed il processore si comportano. Tutto questo per dire che se nel tuo codice metti un controllo Per esempio con i semafori: sem_wait(mutex); completati+=1; sem_signal(mutex); La situazione è cambiata in quanto ora il programma è deterministico. Perdonami per la lunghezza della spiegazione ma ho cercato di essere il più sintetico possibile. Ciao
__________________
Concluso positivamente con: Kamzata, Ducati82, Arus, TheLastRemnant, ghost driver, alexbull1, DanieleRC5, XatiX |
![]() |
![]() |
![]() |
#8 |
Bannato
Iscritto dal: Feb 2013
Messaggi: 1552
|
No, il problema è dell'ottimizzatore, altrimenti ogni tanto funzionerebbe, invece si inceppa sempre.
|
![]() |
![]() |
![]() |
#9 |
Senior Member
Iscritto dal: Feb 2006
Messaggi: 1304
|
Quoto gli altri, quel programma non e' corretto. Il fatto che funzioni senza ottimizzazioni e' un caso.
Inoltre, "volatile" risolve il problema ma per i motivi sbagliati, quello che cerchi (visto che gia' usi C++11) e' atomic. Cambia semplicemente queste due linee Codice:
int completati=0; completati+=1; Codice:
std::atomic<int> completati=0; completati++; ![]() |
![]() |
![]() |
![]() |
#10 |
Bannato
Iscritto dal: Feb 2013
Messaggi: 1552
|
Uhm, niente male questo ATOMIC
![]() |
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 13:05.