- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The program creates four threads that each print a message with a unique id number. Like many threaded programs, it sometimes works correctly even though it contains an error. Can you spot the race condition?
#include#include #define N 4 void* hello (void* myID) { printf ("Hello from thread %d ", *(int *)myID); return NULL; } int main () { int j; pthread_t tid ; for (j = 0; j < N; j++) pthread_create (&tid , NULL, hello, (void *)&j); for (j = 0; j < N; j++) pthread_join (tid , NULL); }
If you see the error, be the first to post the solution and win the forum's ovation and fame forever.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
#include#include #define N 4 DWORD WINAPI hello (LPVOID myID) { printf ("Hello from thread %d ", *(int *)myID); } int main (int argc, char* argv[]) { int j; HANDLE h ; DWORD rc; for (j = 0; j < N; j++) { h = CreateThread (0, 0, hello, (LPVOID)&j, 0, NULL); } rc = WaitForMultipleObjects (N, h, TRUE, INFINITE); }
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
-Dale
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Welcome to the forum! You're the first to join.
You're correct that variable j is incorrectly passed to the threaded function. It's the source of the race condition. You could fix the race condition using a critical section but that would serialize execution, which defeats the purpose of multithreading. There's a better solution that doesn't require synchronization.
Henry
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm sure there are many ways to solve this problem of which my suggestion is only one.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
int id; for (j = 0; j < N; j++) { id = j; pthread_create (&tid , NULL, hello, (void *)&id ); }
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
-Dale
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
-Dale
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
#include
#include
#define N 4
void* hello (void* myID)
{
printf ("Hello from thread %d ", (int)myID);
return NULL;
}
int main ()
{
int j;
pthread_t tid
for (j = 0; j < N; j++)
pthread_create (&tid
for (j = 0; j < N; j++)
pthread_join (tid
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
-Dale
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
To do this safely without serializing thread startup, the simplest thing is to build an array of these structures (if you know the thread count will be constant) or to dynamically create them otherwise. Essentially, it's the same as you handle the array of thread id's in your example code, just extended to the parameter or parameter block passed during thread creation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
"Command" is a useful design pattern here.
struct ICommand
{
virtual void execute () = 0;
};
it's easy to define a framework with something like
Thread *CreateThread (ICommand *cmd);
the command will be executed at thread launch and the instance deleted after execution
the client code will be typically like :
class HenryGCommand : public ICommand
{
const int id;
// typically way more data here
virtual void execute ()
{cout << "Hello from thread " << id << " ";}
public:
HenryGCommand (int vId) : id(vId) {}
};
void Test ()
{
Thread *t
for (int j=0; j
WaitFor(t,N,INFINITE);
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Message Edited by intel.software.network.support on 12-09-2005 01:30 PM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Holy smokes this is old.. but I didn't see a good answer.. but maybe I missed it..
The problem with the code is that we pass the variable J from the caller to the thread by reference. Thread starts require a variable amount of time.. sometimes its fast sometimes it takes awhile.. (this depends if there is pooling, etc.) Because we pass by ref it is possible that, by the time the thread starts, the variable J has been incremented. If this happens we may get four lines saying thread 4 has started or some other erroneous values. J needs to be copied to the thread by value. There are many ways of doing this. Simply passing J in the VOID* would work since they are both 4 bytes.You could also create a class or struct and pass the value inside the pointer to this. However we accomplish this, it must be a separate value from the J that is being incremented by the starting thread.
Chris
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page