View Full Version : [C]Thread
Ciao ragazzi, sono alle prese con la gestione dei thread in C, sotto Windows, facendo uso di Visual C. Il prof ci ha fornito un esempio sulla creazione di un singolo thread:
#include <process.h> /* _beginthread, _endthread */
#include <stdio.h>
void StartPrimo_THread(void *b);
unsigned long c=0;
int fine=0;
void main()
{
char s[2];
int err=_beginthread( StartPrimo_THread, 0, NULL);
if(err==-1) printf("errore ");
else
{
printf("schiaccia un tasto per terminare ");
scanf("%s",s);
fine=1;
printf("%d",c);
}
}
void StartPrimo_THread(void *b)
{
while(fine==0) c++;
_endthread();
}
La funzione _beginthread ha questa sintassi:
unsigned long _beginthread(void( __cdecl *start_address )( void * ), unsigned stack_size, void *arglist );
1.void( __cdecl *start_address )( void * ) che rappresenta la funzione chiamata
2. unsigned stack_size che è la grandezza dello stack di memoria,
3. void *arglist che rappresenta gli argomenti da passare alla funzione
Questo esempio l’ho compreso, ma quando ci ha presentato l’esempio sulla creazione dei thread multipli sono rimasto non poco a bocca aperta. L’esempio è preso direttamente dal codice Microsoft:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt__beginthread.2c_._beginthreadex.asp
Qualcuno di voi mi potrebbe dare una spiegazione un po’ più semplice sulla creazione di thread oppure qualche link dove siano spiegate queste cose? Sul manuale di C ovviamente non si trovano cose riguardanti le API di windows, avete qualche consiglio?
la creazione del thread me la ricordavo diversa, tanto è vero che esiste una funzione CreateThread
cercherò qualche esempio. cmq non c'è niente di difficile
Devo fare uso di _beginthread, la difficoltà sta nel creare due thread paralleli.Se hai visionato l'esempio sul sito della microsoft,vedrai che è un casino (dal momento che si fa un forte uso delle API di windows)!!
Cercavo qualcosa di più semplice. Grazie comunque.
_beginthread è la versione di CreateThread all'interno della libreria di Visual C++...infatti non bisogna linkare alcuna libreria di Windows, ma solo la normale msvcrt...
_beginthread non è un API, ma richiama CreateThread...
Il secondo esempio sul link che hai psotato è importantissimo...serve per sincronizzare due thread (in quel caso quello principale e quello chiamato)...
Ti faccio un esempio davvero bello derivato da quello:
// crt_begthrdex.cpp
// compile with: /MT
#include <windows.h>
#include <stdio.h>
#include <process.h>
unsigned int Counter2 = 0;
unsigned int Counter = 0;
unsigned __stdcall ThirdThreadFunc( void* pArguments )
{
printf( "In third thread...\n" );
while ( Counter2 < 10000000 )
Counter2++;
printf( "Ending third thread...\n" );
_endthreadex( 0 );
return 0;
}
unsigned __stdcall SecondThreadFunc( void* pArguments )
{
HANDLE hThread;
unsigned threadID;
printf( "In second thread...\n" );
printf( "Creating third thread...\n" );
hThread = (HANDLE)_beginthreadex( NULL, 0, &ThirdThreadFunc, NULL, 0, &threadID );
while ( Counter < 20000 ) //a questo punto vanno in parallelo
Counter++;
printf( "Waiting for third thread...\n" );
WaitForSingleObject( hThread, INFINITE ); //attendo che sia terminato il terzo thread
CloseHandle( hThread );
_endthreadex( 0 );
return 0;
}
int main()
{
HANDLE hThread;
unsigned threadID;
printf( "Creating second thread...\n" );
// Create the second thread.
hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );
// Wait until second thread terminates. If you comment out the line
// below, Counter will not be correct because the thread has not
// terminated, and Counter most likely has not been incremented to
// 20000 yet.
WaitForSingleObject( hThread, INFINITE );
printf( "Counter should be 1000000; it is-> %d\n", Counter );
// Destroy the thread object.
CloseHandle( hThread );
}
Grazie per l'aiuto. Purtroppo dovrei fare uso solo di _beginthread (e non _beginthreadex).Mi potresti spiegare la differenza?
Un'altra cosa.Mi manca la documentazione MSDN di Visual C++ 6, sul sito della Microsoft non ho trovato nessun link che mi permetta di scaricarla.Mi puoi aiutare?
P.S
Scusa la risposta tardiva, ho problemi con internet al momento.
// crt_begthrdex.cpp
// compile with: /MT
#include <windows.h>
#include <stdio.h>
#include <process.h>
unsigned int Counter2 = 0;
unsigned int Counter = 0;
unsigned __stdcall ThirdThreadFunc( void* pArguments )
{
printf( "In third thread...\n" );
while ( Counter2 < 10000000 )
Counter2++;
printf( "Ending third thread...\n" );
_endthread();
return 0;
}
unsigned __stdcall SecondThreadFunc( void* pArguments )
{
HANDLE hThread;
printf( "In second thread...\n" );
printf( "Creating third thread...\n" );
hThread = (HANDLE)_beginthread(&ThirdThreadFunc, 0, NULL);
while ( Counter < 20000 ) //a questo punto vanno in parallelo
Counter++;
printf( "Waiting for third thread...\n" );
WaitForSingleObject( hThread, INFINITE ); //attendo che sia terminato il terzo thread
CloseHandle( hThread );
_endthread();
return 0;
}
int main()
{
HANDLE hThread;
printf( "Creating second thread...\n" );
// Create the second thread.
hThread = (HANDLE)_beginthread(&SecondThreadFunc, 0, NULL);
// Wait until second thread terminates. If you comment out the line
// below, Counter will not be correct because the thread has not
// terminated, and Counter most likely has not been incremented to
// 20000 yet.
WaitForSingleObject( hThread, INFINITE );
printf( "Counter should be 20000; it is-> %d\n", Counter );
// Destroy the thread object.
CloseHandle( hThread );
}
L'help di WaitForSingleObject è qui: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/waitforsingleobject.asp
MSDN non si può scaricare...o lo compri o lo consulti online... Sì può scaricare il Platform SDK, ma non contiene le funzioni delle librerie di Visual C++ (come beginthread)...
La funzione:
dwWaitResult=WaitForSingleObject(hMutex,500L);
Testa il mutex per mezzo secondo, se restituisce WAIT_OBJECT_0, la risorsa è libera ed il
thread che la richiede la ottiene; se restituisce WAIT_TIMEOUT significa che la risorsa
non è disponibile. Giusto?
#include <windows.h>
#include <process.h> /* _beginthread, _endthread */
#include <stdio.h>
void Somma( void *ch );
void Sottrai( void *ch );
long a=0;
int fine=0;
HANDLE hMutex;
void main()
{
hMutex = CreateMutex(NULL,FALSE,"Mutex");
if (hMutex == NULL)
printf("errore");
else
{
char scelta[2];
printf("premi un tasto per iniziare ed un altro per terminare ");
scanf("%s",scelta);
_beginthread( Somma, 0, NULL );
_beginthread( Sottrai, 0, NULL );
scanf("%s",scelta);
fine=1;
}
}
//*somma
void Somma(void *ch)
{ DWORD dwWaitResult;
while(fine==0)
{
dwWaitResult = WaitForSingleObject(hMutex,1000);
switch (dwWaitResult)
{
case WAIT_OBJECT_0: //l'oggetto è libero
a++;printf("Somma a=%d\n",a);
Sleep(2000L);
ReleaseMutex(hMutex);
break;
case WAIT_TIMEOUT:printf("Somma time out\n");
break;
case WAIT_ABANDONED: printf("Somma ABANDONED");
break;
}
}
_endthread();
}
//*sottrai
void Sottrai(void *ch)
{ DWORD dwWaitResult;
while(fine==0)
{
dwWaitResult = WaitForSingleObject(hMutex,500);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
a--;printf("Sottrai a=%d\n",a);
Sleep(1500L);
ReleaseMutex(hMutex);
break;
case WAIT_TIMEOUT:printf("Sottrai time out\n");
break;
case WAIT_ABANDONED: printf("Sottrai ABANDONED");
break;
}
}
_endthread();
}
Mandando in esecuzione il seguente codice, noto che la risorsa viene affidata sempre al thread
somma, come mai? C'entra forse il fatto che l'intervallo sleep(2000) e sleep(500) coincidono
ogni 4 "interruzioni"? Mi basta mettere sleep(501) per fare andare anche il thread sottrai
nella regione critica.. Mi fate capire un pò come funziona questa cosa?
Il problema è che i thread sono praticamente sincronizzati... Devi fare in modo di mettere un riatardo variabile...
Ecco con un ritardo variabile come si comportano (ho aggiunto un ritardo variabile anche prima della waitfor...altrimenti si mettevano subito in attesa):
#include <windows.h>
#include <process.h> /* _beginthread, _endthread */
#include <stdio.h>
#include <time.h>
void Somma( void *ch );
void Sottrai( void *ch );
long a=0;
int fine=0;
HANDLE hMutex;
void main()
{
srand(time(NULL));
hMutex = CreateMutex(NULL,FALSE,"Mutex");
if (hMutex == NULL)
printf("errore");
else
{
char scelta[2];
printf("premi un tasto per iniziare ed un altro per terminare ");
scanf("%s",scelta);
_beginthread( Somma, 0, NULL );
_beginthread( Sottrai, 0, NULL );
scanf("%s",scelta);
fine=1;
}
}
//*somma
void Somma(void *ch)
{
DWORD dwWaitResult;
while(fine==0)
{
Sleep((int)(200*((double)rand()/RAND_MAX)));
dwWaitResult = WaitForSingleObject(hMutex,300L);
switch (dwWaitResult)
{
case WAIT_OBJECT_0: //l'oggetto è libero
a++;printf("Somma a=%d\n",a);
Sleep((int)(1000*((double)rand()/RAND_MAX)));
ReleaseMutex(hMutex);
break;
case WAIT_TIMEOUT:printf("Somma time out\n");
break;
case WAIT_ABANDONED: printf("Somma ABANDONED");
break;
}
}
_endthread();
}
//*sottrai
void Sottrai(void *ch)
{
DWORD dwWaitResult;
while(fine==0)
{
Sleep((int)(200*((double)rand()/RAND_MAX)));
dwWaitResult = WaitForSingleObject(hMutex,300L);
switch (dwWaitResult)
{
case WAIT_OBJECT_0:
a--;printf("Sottrai a=%d\n",a);
Sleep((int)(1000*((double)rand()/RAND_MAX)));
ReleaseMutex(hMutex);
break;
case WAIT_TIMEOUT:printf("Sottrai time out\n");
break;
case WAIT_ABANDONED: printf("Sottrai ABANDONED");
break;
}
}
_endthread();
}
grazie. mi potresti spiegare perchè sono sincronizzati?
In pratica prima parte il thread Somma, attende un secondo e avendo trovato la risorsa libera la acquisisce....nel frattempo era partito pure il thread Sottrai che va continuamente in time-out ? Oppure finchè non viene addormentato il thread somma, il thread sottrai non parte? :confused:
Somma...prende la mutex...al 99% perchè parte prima...
Sottrai va in timout 3 volte perchè si è messo in attesa prima della partenza della Sleep...
Sottrai acquisisce la mutex
Somma si mette in attesa
Sottrai si addormenta 1500 ms
Somma va in timeout
Somma acquisisce la mutex...e ricomincia tutto da capo...
Thanks ;)
Sottrai va 3 volte in time-out perchè 500*3=1500<2000, alla successiva chiamata sottrai è a tempo >=2000 e quindi la mutua esclusione gli permette di acquisire la risorsa?
Salve ragazzi, sono alle prese con i semafori,ho il seguente codice:
/*Gestione di 3 parcheggi di 30 posti ciascuno attraverso l'uso dei semafori*/
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#define POSTI 30
#define N 3
#define GetRandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))
void car (void *);
HANDLE hparcheggio[N]; //array di semafori
void main()
{
for(int i=0;i<N;i++)
hparcheggio[i]=CreateSemaphore(NULL,POSTI,POSTI,NULL);
printf(" Digita q per Uscire,I per l'arrivo di un'altra automobile : \n");
do{
_beginthread( car, 0,NULL ); //viene creato un thread per ogni automobile che entra
}while (getchar()!='q');
//Chiudiamo tutti gli oggetti di tipo HANDLE aperti (semafori)
for(i=0;i<N;i++)
CloseHandle(hparcheggio[i]);
}
void car(void *ch)
{
DWORD numeropiano, risultato;
long numeroposto;
risultato=WaitForMultipleObjects(N,hparcheggio,false,INFINITE);
numeropiano=risultato-WAIT_OBJECT_0+1;
printf("la macchina parcheggia al piano %d\n",numeropiano);
srand( _threadid );
int a=GetRandom( 5000, 50000 );
Sleep(a); //specificare un tempo di parcheggio random (tra i 5 e i 50 secondi)
ReleaseSemaphore(hparcheggio[numeropiano-1],1,&numeroposto);
printf("la macchina parcheggiata al piano %d lascia il parcheggio dal posto %d\n" , numeropiano , numeroposto);
_endthread();
}
Non mi è chiara la funzione car che crea i threads.
Innanzitutto vi chiedo, per favore, di spiegarmi il significato del parametro messo a false nella WaitForMultipleObjects.
Win32 SDK dicono:
Specifies the wait type. If TRUE, the function returns when the state all objects in the lpHandles array is signaled.
If FALSE, the function returns when the state of any one of the objects
set to is signaled. In the latter case, the return value indicates the object whose state caused the function to return.
Poi, non ho chiaro come funziona in questo caso la ReleaseSemaphore: perchè come handle del semaforo, passiamo
hparcheggio[numeropiano-1]? E' giusto quel &numeroposto (numeroposto non è stato inizializzato, come funziona)?
Come al solito, vi ringrazio in anticipo!!
Ho capito finalmente.Il 3° parametro della WaitForMultipleObjects messo a false fa si che la
funzione ritorni se uno dei semafori è libero, restituendo l'indice del semaforo libero
Quindi nel mio caso, sei il semaforo 0 è libero ritorna WAIT_OBJECT_0, se è libero il sem
1 allora ritorna WAIT_OBJECT_0+1 etc.
La variabile numeropiano(che avrà valori da 1 a 3) ha adesso un significato.
Non mi è ancora molto chiaro come funziona &numeroposto nella RelaseSemaphore:essa dovrebbe
indicare il valore dell'indirizzo del contatore che aveva precedentemente il semaforo.
Ciao, sto battendo la testa sull'implementazione del problema dei filosofi a cena (comunicazione
tra processi). Per capirci, ho implementato la non-soluzione del problema (avete presente
il testo del Tanenbaum,I moderni Sistemi Opeartivi), ossia quella in cui sorge il problema
se i filosofi (i thread) partono contemporaneamente per l'accesso delle forchette (le risorse)
per mangiare.Qualcuno di voi ha mai implementato la soluzione del Tanenbaum in C?
Ho fatto questa, ma non mi funziona, subito mi esce da tutti i thread
#include <windows.h>
#include <process.h> /* _beginthread, _endthread */
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#define N 5 //numero di filosofi
#define LEFT (c-1)%N //numero del vicino di sinistra
#define RIGHT (c+1)%N //numero del vicino di destra
#define THINKING 0 //filosofo pensante
#define HUNGRY 1 //filosofo affamato
#define EATING 2 //filosofo che mangia
HANDLE hforchetta[N]; //l'array di semafori
HANDLE SemMutex; //Per la mutua esclusione
int vmang[N]; //numero di volte che ogni filosofo mangia
int stato[N]; //vettore per tenere traccia dello stato di ogni filosofo(mangiano,pensano o sono affamati)
int c; //filosofo
int fine=0;
/*Funzioni necessarie al problema*/
void Filosofi(void *ch);
void prendiFork(int c); //c: quale filosofo da 0 a N-1
void lasciaFork(int c);
void test(int c); //per testare lo stato dei filosofi vicini a chi vuole mangiare
int main()
{
SemMutex=CreateSemaphore(NULL, 1,1,NULL);
for (int i=0;i<N;i++)
{
hforchetta[i] = CreateSemaphore(NULL, 1,1,NULL);
vmang[N]=0; //nessun filosofo ha ancora mangiato
}
printf(" Digita un tasto per Uscire \n");
int namefilo[N];
for ( i=0;i<N;i++)
{
namefilo[i]=i; //filosofo0=0, filosofo1=1.....
_beginthread( Filosofi, 0, (void *) &namefilo[i]);
}
getch();
for ( i=0;i<N;i++)
{
printf("Il filosofo %d ha mangiato %d volte\n",i+1,vmang[i]);
CloseHandle(hforchetta[i]);
}
CloseHandle(SemMutex);
fine=1;
return 0;
}
/////////////////
void Filosofi(void *ch)
{
/*Tutto questo lavoro per convertire ch (puntatore ad un void) in un intero*/
int *b;
b=(int *)ch;
c=*b; //in c mettiamo il contenuto di b
/*Bastava scrivere c=*((int *)ch); per compiere lo stesso lavoro delle 3 righe sopra*/
while(fine==0)
{
prendiFork(c);
lasciaFork(c);
}
_endthread();
}
void prendiFork(int c)
{
DWORD risMut;
risMut=WaitForSingleObject(SemMutex,INFINITE);
switch (risMut)
{
case WAIT_OBJECT_0:
stato[c]=HUNGRY;
test(c);
ReleaseSemaphore(SemMutex,1,NULL);
//Si blocca se le forchette non sono state ottenute
DWORD risForkD,risForkS;
printf("il filosofo %d e' in attesa delle forchette (pensa) \n",c+1);
risForkD=WaitForSingleObject(hforchetta[RIGHT],INFINITE);
if (risForkD==WAIT_OBJECT_0)
{
printf("il filosofo %d ha preso la forchetta destra \n",c+1);
risForkS=WaitForSingleObject(hforchetta[LEFT], INFINITE);
if (risForkS==WAIT_OBJECT_0)
{
printf("il filosofo %d ha preso anche la forchetta sinistra e inizia a mangiare\n",c+1);
vmang[c]++; //vmang[c]=vmang[c]+1;
Sleep(2000); //il filosofo mangia
printf("il filosofo %d sta per smetter di mangiare (lascia le forchette)\n",c+1);
ReleaseSemaphore(hforchetta[LEFT],1,NULL);
ReleaseSemaphore(hforchetta[RIGHT],1,NULL);
printf("il filosofo %d sta iniziando a pensare\n",c+1);
Sleep(2000); //il filosofo pensa
printf("il filosofo %d ha smesso di pensare e vorrebbe mangiare\n",c+1);
}
else
{
ReleaseSemaphore(hforchetta[RIGHT],1,NULL);
printf("il filosofo %d si e' stancato di aspettare la sinistra e lascia la destra \n",c+1);
}
break;
}
}
}
void lasciaFork(int c)
{
DWORD risMut;
risMut=WaitForSingleObject(SemMutex,INFINITE);
switch (risMut)
{
case WAIT_OBJECT_0:
stato[c]=THINKING;
test(LEFT);
test(RIGHT);
ReleaseSemaphore(SemMutex,1,NULL);
break;
}
}
void test(int c)
{
if ((stato[c]==HUNGRY) && (stato[LEFT]!=EATING) && (stato[RIGHT]!=EATING))
{
stato[c]=EATING;
ReleaseSemaphore(hforchetta[c],1,NULL);
}
}
Ciao, dovrei risolvere il seguente esercizio:
Preparare un programma che generi 5 thread che dopo un certo tempo t calcolato randomicamente scrivano su di un file condiviso il tempo t ed l'eventuale tempo di attesa aggiuntivo di attesa per il rilascio del file da parte di un altro thread.
Note:
Vorrei fare uso degli "Eventi", a quanto pare il loro uso è preferibile rispetto all'uso dei mutex, dal momento che è possibile gestire manalmante lo stato "signaled" o non "signaled" di un oggetto.Ho provato a fare una bozza del programma, come inizio che ne dite?Momentaneamente vorrei concentrarmi sul fatto di aprire il file e scriverci qualcosa, ovviamente gestendo l'apertura di esso in maniera efficente. Forse con un mutex verrebbe più facile a gestire la situazione, vorrei però imparare ad usare gli eventi.
La mia bozza:
#include <stdio.h>
#include <windows.h>
#include <process.h>
#define GetRandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))
/*I 5 thread*/
void Primo(void *dummy);
void Secondo(void *dummy);
void Terzo(void *dummy);
void Quarto(void *dummy);
void Quinto(void *dummy);
/*Variabili globali*/
FILE *fp;
int main ()
{
HANDLE hEvent, hThreads[5];
DWORD dwThreadId[5];
printf ("Creazione dell'evento...\n");
hEvent=CreateEvent(NULL,TRUE,FALSE,"TestEvent");
printf ("Creazione del thread Primo\n");
hThreads[0]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) Primo, NULL, 0, &dwThreadId[0]);
printf ("Creazione del thread Secondo\n");
hThreads[1]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) Secondo, NULL, 0, &dwThreadId[1]);
printf ("Creazione del thread Terzo\n");
hThreads[2]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) Terzo, NULL, 0, &dwThreadId[2]);
printf ("Creazione del thread Quarto\n");
hThreads[3]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) Quarto, NULL, 0, &dwThreadId[3]);
printf ("Creazione del thread Quinto\n");
hThreads[4]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) Quinto, NULL, 0, &dwThreadId[4]);
//continua....
return 0;
}
void Primo(void *dummy)
{
HANDLE hEvent;
DWORD dwWaitResult;
printf ("Il thread Primo e' partito\n");
hEvent=OpenEvent(EVENT_MODIFY_STATE|SYNCHRONIZE, FALSE,"TestEvent");
printf("Thread Primo: Evento aperto con successo\n");
dwWaitResult=WaitForSingleObject(hEvent,INFINITE);
if (dwWaitResult==WAIT_OBJECT_0)
{
//Provo ad aprire il file ed eventualmente scrivo in esso
}
}
Domande:
1) hEvent lo devo dichiarare come variabile globale?
2)Nella creazione dei thread è giusto che non passi alcun parametro al thread?
hThreads[0]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) Primo, NULL, 0, &dwThreadId[0]);
Grazie a chi mi darà un aiutino!!
Il secondo esempio sul link che hai psotato è importantissimo...serve per sincronizzare due thread (in quel caso quello principale e quello chiamato)...
Ti faccio un esempio davvero bello derivato da quello:
// crt_begthrdex.cpp
// compile with: /MT
#include <windows.h>
#include <stdio.h>
#include <process.h>
unsigned int Counter2 = 0;
unsigned int Counter = 0;
unsigned __stdcall ThirdThreadFunc( void* pArguments )
{
printf( "In third thread...\n" );
while ( Counter2 < 10000000 )
Counter2++;
printf( "Ending third thread...\n" );
_endthreadex( 0 );
return 0;
}
unsigned __stdcall SecondThreadFunc( void* pArguments )
{
HANDLE hThread;
unsigned threadID;
printf( "In second thread...\n" );
printf( "Creating third thread...\n" );
hThread = (HANDLE)_beginthreadex( NULL, 0, &ThirdThreadFunc, NULL, 0, &threadID );
while ( Counter < 20000 ) //a questo punto vanno in parallelo
Counter++;
printf( "Waiting for third thread...\n" );
WaitForSingleObject( hThread, INFINITE ); //attendo che sia terminato il terzo thread
CloseHandle( hThread );
_endthreadex( 0 );
return 0;
}
int main()
{
HANDLE hThread;
unsigned threadID;
printf( "Creating second thread...\n" );
// Create the second thread.
hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );
// Wait until second thread terminates. If you comment out the line
// below, Counter will not be correct because the thread has not
// terminated, and Counter most likely has not been incremented to
// 20000 yet.
WaitForSingleObject( hThread, INFINITE );
printf( "Counter should be 1000000; it is-> %d\n", Counter );
// Destroy the thread object.
CloseHandle( hThread );
}
ho provato questo esempio ma l due thread a me non si sincronizzano affatto: perchè ?
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.