|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
[C/C++] problemi coi thread
ciao,
ho due thread che ho chiamato come di consueto PRODUTTORE e CONSUMATORE. Il produttore popola una array mentre come viene ovvio pensare CONSUMATORE lo usa. Ho settato una variabile semaforica in modo che il CONSUMATORE non può accedere all'array sino a quando questo non è aggiornato completamente e da qui il problema: come faccio a fare in modo che l'aggiornamento non avvenga a CPU time ma ad esempio ogni 50 ms mentre il consumatore fa la sua parte ogni 250 ms ? Essendoci in mezzo il semaforo se ritardo il produttore di conseguenza ritardo anche il consumatore ma desidererei tenere separati i due thread in modo che i rispettivi "lavori" avvengano in tempi differenti per mantenendo i vincoli dell'accesso all'array da parte del consumatore. grazie |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
edit
Ultima modifica di misterx : 13-04-2011 alle 05:47. |
![]() |
![]() |
![]() |
#3 |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Risposta banale (spero di non suggerirti cavolate): fai eseguire a entrambi i thread (quando non hanno il lock sull'array ovviamente) una sleep; prodottore dormirà 50ms, consumatore dormirà 250ms.
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
![]() |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
Quote:
Magari è la mia implementazione ad essere bacata. Codice:
semaforo=0; thread_1 { if(semaforo==0) { popola array; } semaforo=1; } thread_2 { if(semaforo==1) { consumaa array; } semaforo=0; } |
|
![]() |
![]() |
![]() |
#5 | |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
Nell'ipotesi che sia vera la prima affermazione, e' relativamente semplice: devi avere due scheduler distinti nel primo e secondo thread. Uno impostato a 250ms e l'altro a 50ms. Se il tuo ambiente non te fornisce si puo' crearne uno a base di (sotto unix) clock_gettime e clock_nanosleep (o le equivalenti sotto windows). Devi solo tenere presente che non puoi fare semplicemente una sleep di 50ms, ma devi tenere conto di quanto dura il singolo loop Fatto questo, non devi far altro che fare una cosa come la seguente: Codice:
// producer scheduler sched(50000); // usec while(!done) { do_something(); lock_array(); perform_changes(); unlock_array(); sched.wait_next(); } // consumer scheduler sched(250000); // usec while(!done) { lock_array(); read_changes(); unlock_array(); do_something_else(); sched.wait_next(); }
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
![]() |
![]() |
![]() |
#6 | |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
grazie marco.r
quello che interessa a me è avere sempre l'array aggiornato ma impedire che il consumatore vi acceda se non è stato completamente aggiornato. Il semaforo risponde allo scopo ma i due thread viaggiano sincroni anzi, il più lento "rallenta" quello più veloce. Sto sviluppando in Borland Builder C++ |
![]() |
![]() |
![]() |
#8 | |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
Come ti suggerisco io invece, con u nsemplice lock, il produttore puo' bloccare/sbloccare l'accesso all'array quante volte vuole, ma essendo sincronizzato, cmq produttore e consumatore non possono accedervi contemporaneamente per usare la tua notazione, dovresti usare qualcosa tipo Codice:
semaforo=0; thread_1 { popola_array(); sem_post(semaforo); while( ... ) { aspetta prossimi 50ms sem_wait(semaforo); popola array; sem_post(semaforo); } } thread_2 { while( ... ) { aspetta prossimi 250ms sem_wait(semaforo); consumaa array; sem_post(semaforo); } }
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele Ultima modifica di marco.r : 13-04-2011 alle 15:48. |
|
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
Quote:
Codice:
int array[100]; thread_1 { while(1) { Sleep(50); for(i=0; i<100; i++) array[i]=rand(); } } thread_2 { while(1) { Sleep(250); for(i=0; i<100; i++) printf("%d\n",array[i]); } } |
|
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
ora ho capito cosa intendevi, così funziona molto bene
Codice:
int array[100]; thread_1 { while(1) { sem=0; for(i=0; i<100; i++) array[i]=rand(); sem=1; Sleep(50); } } thread_2 { while(1) { if(sem==1) { for(i=0; i<100; i++) printf("%d\n",array[i]); } Sleep(250); } } Ultima modifica di misterx : 13-04-2011 alle 19:22. |
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Non puoi usare una semplice variabile per la sincronizzazione. Innanzi tutto non puoi garantire che l atray venga copiato ogni 250 ms. Perché invece di attendere che venga finita la scrittura dal produce, aspetti la volta dopo. Potenzialmente se hai sfoga la copia non avviene mai. Peggio ancora eventuali ottizzazioni del compilatore possono causare problemi di sincronizzazione del valore del semaforo tra due thread.
Invece che un intero usa un semaforo vero e proprio o più precisamente un mutex. Li trovi tra le api di windows
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
![]() |
![]() |
![]() |
#12 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
ed haai ragione. Funzionava meglio la prima implementazione mentre questa seconda potrebbe avvenire che il produttore porta a termine sempre il suo compito ma quando termina e parte il consumatore, se il thread consumatore finisce il suo quantum di tempo a disposizione, si torna al produttore che inibisce il funzionamento del consumatore
![]() non ho mai usato i mutex ![]() |
![]() |
![]() |
![]() |
#13 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
ciao,
non sono molto convinto di come sto usando i mutex Codice:
int array[100]; /* PRODUTTORE */ hMutex=CreateMutex(NULL, FALSE,NULL); while(.....) { WaitForSingleObject(hMutex,INFINITE); for(int i=0; i<100; i++) array[i]=rand(); ReleaseMutex(hMutex); Sleep(50); } /* CONSUMATORE */ hMutex=CreateMutex(NULL, FALSE,NULL); while(.....) { WaitForSingleObject(hMutex,INFINITE); for(int i=0; i<100; i++) printf(%d\n,array[i]); ReleaseMutex(hMutex); Sleep(250); } funziona a questo modo ? Come lo verifico ? grazie 1000 |
![]() |
![]() |
![]() |
#14 |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Devi usare lo stesso mutex, oppure crearlo "named"(non ho idea di come si faccia sotto windows) usando lo stesso nome in entrambi i thread.
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
ma va creato un mutex globale allora ?
Oppure si crea un mutex PRODUTTORE e lo si usa in consumatore e viceversa? Non mi è chiaro il meccanismo ![]() |
![]() |
![]() |
![]() |
#16 |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Ti serve un unico mutex. Concettualmente e'come la variabile intera che usavi tu, solo che e' implementata opportunamente.
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
![]() |
![]() |
![]() |
#17 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
ho fatto cisì e sembra funzionare
Codice:
int array[100]; hMutex=CreateMutex(NULL, FALSE,NULL); /* PRODUTTORE */ while(.....) { WaitForSingleObject(hMutex,INFINITE); /* SEZIONE CRITICA */ for(int i=0; i<100; i++) array[i]=rand(); /* FINE SEZIONE CRITICA */ ReleaseMutex(hMutex); Sleep(50); } /* CONSUMATORE */ while(.....) { WaitForSingleObject(hMutex,INFINITE); /* SEZIONE CRITICA */ for(int i=0; i<100; i++) printf(%d\n,array[i]); /* FINE SEZIONE CRITICA */ ReleaseMutex(hMutex); Sleep(250); } Mi chiedo però se la parte di codice sottostante a WaitForSingleObject(hMutex,INFINITE); viene eseguita completamente sino al ReleaseMutex(hMutex); ? |
![]() |
![]() |
![]() |
#18 | |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
Se e' quel che penso io, la risposta e' si', ovvero quando tu chiami WaitForSingleObject e qualcun altro l'ha gia' fatto, il thread resta in attesa finche' l'altro non chiama ReleaseMutex. per cui solo uno alla volta dei due thread esegue la parte tra le due chiamate.
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
![]() |
![]() |
![]() |
#19 | |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
Quote:
![]() Ultima modifica di misterx : 18-04-2011 alle 05:57. |
|
![]() |
![]() |
![]() |
#20 |
Senior Member
Iscritto dal: Apr 2001
Città: Milano
Messaggi: 3736
|
c'è un aspetto che non avevo considerato: se ora devo riordinare in tempo reale una parte dell'array prima che venga usato da "consumatore" devo usare mutex ed un nuovo thread vero?
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 13:33.