Results 1 to 4 of 4
Hi guys
I have a question about thread programming. Based on the material on the web, I created a simple program that would create a bunch of threads in a ...
- 12-02-2011 #1Just Joined!
- Join Date
- Nov 2011
- Posts
- 12
Question about pthreads
Hi guys
I have a question about thread programming. Based on the material on the web, I created a simple program that would create a bunch of threads in a loop like this:
#define N_THREADS 5
void* thread_function(void*);
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
int main()
{
int i;
int j;
int i_ptr=&i;
pthread_t threads[N_THREADS];
for(i=0; i < N_THREADS; i++)
{pthread_create( &threads[i], NULL, thread_function, (void*) i_ptr);
//sleep (1);}
for(j=0; j < N_THREADS; j++) pthread_join( threads[j], NULL);
return (0);
}
void* thread_function(void* data)
{
pthread_mutex_lock( &mutex1 );
int thread_data=*(int*)data;
counter++;
printf("I am thread number %d Counter value is %d\n",thread_data, counter);
pthread_mutex_unlock( &mutex1 );
pthread_exit("NULL");
}
When I execute the code above, I should normally get:
I am thread number 0 Counter value is 1
I am thread number 1 Counter value is 2
I am thread number 2 Counter value is 3
I am thread number 3 Counter value is 4
I am thread number 4 Counter value is 5
But instead i get:
I am thread number 1 Counter value is 1
I am thread number 5 Counter value is 2
I am thread number 5 Counter value is 3
I am thread number 5 Counter value is 4
I am thread number 5 Counter value is 5
or
I am thread number 1 Counter value is 1
I am thread number 5 Counter value is 3
I am thread number 2 Counter value is 2
I am thread number 5 Counter value is 4
I am thread number 5 Counter value is 5
or even(!):
I am thread number 5 Counter value is 1
I am thread number 5 Counter value is 2
I am thread number 5 Counter value is 3
I am thread number 5 Counter value is 4
I am thread number 5 Counter value is 5
Counter values seem to be fine, but why is the thread numbers not working properly? When i debug it with gdb, it works fine. When I add the sleep in the first loop, i also get correct output.
What could be the reason for this weird behavior?
- 12-02-2011 #2Linux Newbie
- Join Date
- Mar 2010
- Posts
- 121
Please use code tags for code!
When you create your thread, you're passing in a pointer to a variable on the stack, and it's the same address for each thread. Since there is no guarantee that threads run immediately or in sequence, your main loop may have (in this case, has) incremented the variable at the location the thread function reads, so changing what the thread function reads.
The solution is to (a) use a key, (b) in the case of simple data types like the int you're using, cast to and from:
or (c) use an array of int values so you pass in the address to a different one each time.Code:void *thread_func(void *arg) { int i = (int)arg; // } void whatever() { int i = 1; pthread(thread, NULL, &thread_func, (void *)i); }
- 12-05-2011 #3Just Joined!
- Join Date
- Nov 2011
- Posts
- 12
Dear John,
Thanks for the explanation but it's not so clear from what you've just written. Your modification of the code has worked, but could you explain it more simply and clearly?
PS. Sorry for the code tags, I am new to the forum
- 12-05-2011 #4Linux Newbie
- Join Date
- Mar 2010
- Posts
- 121
Here's a simple "example trace" of the steps your program might take. I've only gone up to just after the launch of the first thread, since this will be enough to demonstrate the problem. Let's assume for simplicity that the i in your main function is located at address 10 (not that it ever will be, but hey...).
When reading this (and indeed, when dealing with threaded applications) it's important to keep in mind that the OS's thread scheduler very deliberately makes absolutely no guarantees about when which threads will get executed. In particular in your case, it does not guarantee (or even attempt to guarantee) that a newly created thread will have started running/executed any instructions before pthread_create() returns.
Code:/*** In main thread. ***/ // 'i' declared, and is on the stack int i; // Located at address 10. // Start our 'for' loop, so i is set to 0. i = 0; // Create the first thread. Remember, there's no guarantee it'll // run immediately. // Note the value we've passed in is (void *)10. pthread_create(&threads[i], NULL, &thread_func, (void *)&i); // Still in the main thread, i gets incremented. i++; // i is now 1, and thus the value at address 10 is now 1. /*** Context switch to thread 1 ***/ // We're now in the first thread - we've started execution in // thread_func(). void *thread_func(void *data) { // Let's dereference our pointer. It's pointing to address 10, // and I guess you know what's there... int thread_data=*(int*)data; // At this point, thread_data is equal to whatever was at // address 10 - i.e. 1.


Reply With Quote