2
#include <pthread.h>
#include <stdio.h>

void* printHello (void* threadId)
{
    pthread_t *my_tid = (pthread_t *)threadId;
    printf ("\nIn `printHello ()`: thread id %ld", (long)*my_tid);
    pthread_exit (NULL);
}

int main ()
{
    pthread_t        arrayOfThreadId [5];
    int                  returnValue;
    unsigned int iterate;

    for (iterate = 0; iterate < 5; iterate++)
    {
        if (returnValue = pthread_create (&arrayOfThreadId [iterate],
                                    NULL,
                                    printHello,
                                    (void*) &arrayOfThreadId [iterate]) != 0)
        {
            printf ("\nerror: pthread_create failed with error number %d", returnValue);
        }
        else
        {
            printf ("\nIn `main()`: creating thread %ld", arrayOfThreadId [iterate]);
        }
    }

    printf ("\nBefore `return 0;` in `main()`");
    pthread_exit (NULL);
    return 0;
}

Output:

In 

`main()`: creating thread 139683073914640
In `main()`: creating thread 139683065521936
In `main()`: creating thread 139683057129232
In `main()`: creating thread 139683048736528
In `main()`: creating thread 139683040343824
Before `return 0;` in `main()`
In `printHello ()`: thread id 140735115959408
In `printHello ()`: thread id 4195680
In `printHello ()`: thread id 0
In `printHello ()`: thread id 0
In `printHello ()`: thread id 139683073914640

Why do the threadIDs differ?

I missing some point here. I have done accidentally wrong, it seems.

Aquarius_Girl
  • 21,790
  • 65
  • 230
  • 411

1 Answers1

4

You're passing the address of your threadId, but you're casting that address to a pthread_t, thus treating the address of an element in your arrayOfThreadId as if it were a pthread_t.

Do this instead:

void* printHello (void* threadId)
{
    pthread_t *my_tid = threadId;
    printf ("\nIn `printHello ()`: thread id %ld\n", (long)*my_tid);

And make sure your main() does not exit until all the threads are finished, else you risk having the array destroyed before the threads pokes into it.

nos
  • 223,662
  • 58
  • 417
  • 506
  • `pthread_t *my_tid = threadId;`results in`error: invalid conversion from ‘void*’ to ‘pthread_t*’ ` – Aquarius_Girl Feb 09 '12 at 09:14
  • Correct your answer, it has to be: `pthread_t *my_tid = (pthread_t *)threadId;` – Aquarius_Girl Feb 09 '12 at 09:22
  • Anyway, the problem still persists. – Aquarius_Girl Feb 09 '12 at 09:23
  • 1
    @Anisha Kaul, in C, you do NOT need to cast a void*, the cast in (pthread_t *)threadId; is not needed. You are compiling your code as C++, not C if you get the error you mentioned. You still need to ensure that main() does not exit before the threads do. If the problem still presist, there's something other wrong with the code you have. – nos Feb 09 '12 at 11:36
  • I am on GCC, and your code gives me the "error". I wrote that after testing it... and now when I look at it again, I realize that I had saved that file with extension `.cpp` and was compiling it with `gcc`?? But still, since the compiler gcc works for C so it shouldn't have given me the error, but it did :doh: I'll present the changed code again. – Aquarius_Girl Feb 09 '12 at 11:47
  • 1
    gcc compiles files ending with .cpp as C++. – nos Feb 09 '12 at 11:49
  • Ah, great, I never knew that, then why do we "need" g++? Anyway :) – Aquarius_Girl Feb 09 '12 at 11:50
  • The last suggestion won't work - it'll pass whatever is in `arrayOfThreadId[iterate]` (which is indeterminate) from before the `pthread_create()` call. – Michael Burr Feb 09 '12 at 19:59
  • 1
    @Anisha: the difference between `gcc` and `g++` (as far as C/C++ goes): http://stackoverflow.com/a/5854712/12711 – Michael Burr Feb 09 '12 at 21:54
  • nos, and @MichaelBurr I have added ALL the modified code, the problem persists. – Aquarius_Girl Feb 10 '12 at 06:18
  • @Anisha: instead of calling `pthread_exit()` near the end of main, wait for the threads to complete using `pthread_join()` on each of them: `for (iterate=0;iterate<5;iterate++) { void* v; pthread_join( arrayOfThreadId[iterate], &v); }` – Michael Burr Feb 10 '12 at 07:19
  • @MichaelBurr Is that the cause of this problem? or you are stating it as a generic tip? – Aquarius_Girl Feb 10 '12 at 07:27
  • 2
    @Anisha It's a problem with the code that must be fixed. Even just doing a sleep(2); before pthread_exit(NULL); in main() might alter the behavior. (if main() exits, the arrayOfThreadId array is no longer valid, so the threads you create might read garbage from it) – nos Feb 10 '12 at 07:48
  • Nos, that makes sense. I'll change it and then post back. – Aquarius_Girl Feb 10 '12 at 07:51
  • Note that I think there is still technically a race condition on the `arrayOfThreadId[]` entries. I don't think that `pthread_create()` is guaranteed to have updated the passed in `pthread_t` object before the created thread gets a chance to start running. – Michael Burr Feb 10 '12 at 08:01
  • @MichaelBurr Why do you think so, and what's the way to correct that? – Aquarius_Girl Feb 10 '12 at 08:45
  • `pthread_create()` isn't required to put the `pthread_t` data into the passed in location until sometime before it returns to the caller (assuming success). It could create the thread, let it start, then do some work to create a `pthread_t` object to copy back to the caller. During that short period of time, the thread can access its argument, which in your program is the location that the `pthread_t` data will be put into (but maybe hasn't gotten there yet). The general way to fix this is to synchronize access to the variable passed in to the thread, using perhaps a `pthread_mutex_t`. – Michael Burr Feb 10 '12 at 09:01
  • I'm assuming that you're passing in the thread's ID just for demo purposes - if you're really interested in the thread getting access to it's ID an easier way that doesn't run into race conditions is to have the thread call `pthread_self()`. But like I said, I assume that the synchronization between the thread and its creator is what's important in your question, not that the thread get a hold of its ID. – Michael Burr Feb 10 '12 at 09:04
  • @MichaelBurr If you don't write @Anisha I won't get the notifications. Anyway, the man page says `Before returning, a successful call to pthread_create() stores the ID of the new thread in the buffer pointed to by thread;` – Aquarius_Girl Feb 10 '12 at 09:29
  • @Anisha Kaul But it doesn't say that it stores it successfully before your thread is run. Your thread should just call pthread_self() to get its own pthread_t. Anyway, the example code as is, with main doing pthread_join, has worked for me on Solaris, Debian SID 32/64 bit, Centos 64bit, FreeBSD 64bit. – nos Feb 10 '12 at 10:08
  • The pthread_join made your code work for me. Thanks to nos, and @MichaelBurr too. – Aquarius_Girl Feb 16 '12 at 08:11