Reputation: 483
#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <windows.h>
#include <process.h>
using namespace std;
HANDLE ghEvents;
struct DataStructure
{
int r[2];
int h;
};
unsigned __stdcall f2(void *p)
{
DataStructure *input = (DataStructure *)p;
int i = (int)input->h;
cout <<i<<endl;
}
int main()
{
HANDLE hThread[8];
DWORD i, dwEvent, dwThreadID;
unsigned threadID;
DataStructure input;
ghEvents = CreateEvent(NULL,FALSE,FALSE,NULL);
for (int i = 0; i < 8; i++)
{
input.h=i;
hThread[i] = (HANDLE)_beginthreadex( NULL, 0, f2, (void*)&input, 0, &threadID );
}
dwEvent = WaitForMultipleObjects(8,hThread,TRUE,INFINITE);
CloseHandle(ghEvents);
for (int i = 0; i < 8; i++)
{
CloseHandle( hThread[i] );
}
cin.get();
return 0;
}
The output is 77777777 instead of 12345678.
I know i have to pass the input by value and not reference but it keeps giving me an error message, what is the proper way to do it?
Upvotes: 0
Views: 496
Reputation: 60017
This is subsequent to my previous answer as is a better solution if the number of threads is known at compile time.
DataStructure input[8];
...
for (int i = 0; i < 8; i++)
{
input[i].h=i;
hThread[i] = (HANDLE)_beginthreadex( NULL, 0, f2, (void*)&input[i], 0, &threadID );
}
And you need to return a value:
unsigned __stdcall f2(void *p)
{
DataStructure *input = (DataStructure *)p;
int i = input->h;
cout <<i<<endl;
return 0;
}
Upvotes: 1
Reputation: 60017
You need to create the data structure for each of the threads as you are overwriting the value of input.h for each of the threads.
So to fix, change it to
DataStructure *input;
...
for (int i = 0; i < 8; i++)
{
input = new DataStructure ;
input->h=i;
hThread[i] = (HANDLE)_beginthreadex( NULL, 0, f2, (void*)input, 0, &threadID );
}
And to avoid a memory leak get the f2 function to delete the input i.e.
unsigned __stdcall f2(void *p)
{
DataStructure *input = (DataStructure *)p;
int i = input->h;
cout <<i<<endl;
delete input;
return 0;
}
note This solution uses dynamic memory allocation as is good solution if the number of threads are unknown at compile time. See my other answer if the number of threads is known.
Upvotes: 0
Reputation: 4217
You are giving each thread the address of the same DataStructure
. Your output is non-deterministic. Depending on when each thread gets to run, they may read before, during, or after another iteration of that loop. Meaning, by the time the thread spins up and gets to access input->h
, the main thread may have already continued on and changing input.h
to the next iteration.
Example:
input.h
to 0.input
as a parameter.input.h
to 1.input
as a parameter.input.h
to 2. input
as a parameter. input.h
to 3.input->h
as 3. input
as a parameter. input->h
as 3. input.h
to 4.input->h
as 4. input->h
as 4.input->h
as 4.Final Output: 3344
Give each thread a different DataStructure
so that they are not trying to read from the same memory address. This way, there is no race-condition. The term refers to the fact that thread start up and order of execution is not guaranteed, so if threads are accessing the same resources without synchronization being done, they will "race".
Upvotes: 1
Reputation: 63250
First point is:
You have no synchronization in place for your datastructure which is being passed to multiple threads, and while these threads are doing something with it, you're already going through the next iteration of the loop and changing the value of your datastructure.
Create a new datastructure inside a the loop to avoid having synchronization issues.
Upvotes: 0