• C

pThread PROBLEMS

Hi,
I am doing some programing using linux version of pThread.  I have created 5 threads. My first question is how do I get each thread's id? Also lets say I have a variable X. How do I change the value of this variable using thread 1 and then change the new value using thread 2. I guess I need the X var to be shared such that all threads have access to it. Here is what I have got so far.

main()
{
      pthread_t thread1, thread2, thread3, thread4, thread5;
      char *message1 = "Thread 1";
      char *message2 = "Thread 2";
      char *message3 = "Thread 3";
      char *message4 = "Thread 4";
      char *message5 = "Thread 5";
      int  iThread1, iThread2, iThread3, iThread4, iThread5;
      int x = 36;

      iThread1 = pthread_create(&thread1, NULL, function, message1);
      iThread2 = pthread_create(&thread2, NULL, function, message2);
      iThread3 = pthread_create(&thread3, NULL, function, message3);
      iThread4 = pthread_create(&thread4, NULL, function, message4);
      iThread5 = pthread_create(&thread5, NULL, function, message5);

/* the following is wrong because it just prints 0 meaning that the thread was */
/* created successfully. I want the ID of each thread to be printed */

      cout << "Thread 1 ID: " << iThread1 << endl;
      cout << "Thread 2 ID: " << iThread2 << endl;
      cout << "Thread 3 ID: " << iThread3 << endl;
      cout << "Thread 4 ID: " << iThread4 << endl;
      cout << "Thread 5 ID: " << iThread5 << endl;
      exit(0);
}

Thanks in advance.
_mssAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Kent OlsenDBACommented:
Hi _mss,

Threads are not tasks.  They are merely multiple execution points in the same program.  All memory in the program is shared by all of the threads so any time a thread changes a variable, all of the other threads immediately pick up the change.


Good Luck!
Kent
Kent OlsenDBACommented:
Hi _mss,

Oh yeah.  :)  pthread_create() returns the ID of the just created thread.

Kent
_mssAuthor Commented:
But how do you use threada to change the value of a variable. and then use thread 2 to change it again.
_mssAuthor Commented:
pthread_create just returns 0 if the thread was created successfully or other numbers if there were errors etc.
Tim_UtschigCommented:
From man pthread_create:

    RETURN VALUE
           On  success,  the  identifier  of  the  newly created thread is stored in the location pointed by the
           |thread| argument, and a 0 is returned. On error, a non-zero error code is returned.

So thread1, thread2, thread3, thread4, and thread5 contain your thread IDs.
_mssAuthor Commented:
I see, any idea on how change the value of a variable using multiple threads. I am thinking something like this.

for (int i = 0; i <= 10; i++)
{
      threadi.increment(x by 1);
}
Kent OlsenDBACommented:
Hi Tim_Utschig,

Whoops.  :/  Thanks for cleaning that up Tim.  Got to typing faster than I was thinking.....

>>But how do you use threada to change the value of a variable. and then use thread 2 to change it again?

Just change the variable.  The other thread will see it.

A good example and test is to create a variable ThreadLock to handle some handshaking between them.

int  ThreadLock;

     ThreadLock = 0;
     iThread1 = pthread_create(&thread1, NULL, function, message1);
     iThread2 = pthread_create(&thread2, NULL, function, message2);

     ThreadLock = iThread1;


Then within Thread1, loop on the variable ThreadLock.  When (ThreadLock == thread1) then have the thread set ThreadLock to thread2.

Have Thread2 loop on the variable, too, except that it's waiting on (ThreadLock == thread2).


This way, the threads are locked out until the value of ThreadLock is the thread id.  Then the thread changes the value in ThreadLock and moves on.


Kent
Tim_UtschigCommented:
Here's an example using a mutex to control access to a variable:

#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t  mutex;
int              shared_var = 0;

void* routine(void *arg) {
    int status, i;

    for(i = 0; i < 3; i++) {
        printf("%s: Acquiring lock...\n", (char*)arg);
        if((status = pthread_mutex_lock(&mutex)) != 0) {
            fprintf(stderr, "%s: pthread_mutex_lock() failed: %s (%d)",
                    (char*)arg, strerror(status), status);
            return NULL;
        }

        printf("%s: Incrementing shared_var (currently %d).\n", (char*)arg, shared_var);
        shared_var++;
       
        printf("%s: Releasing lock...\n");
        if((status = pthread_mutex_unlock(&mutex)) != 0) {
            fprintf(stderr, "%s: pthread_mutex_unlock() failed: %s (%d)",
                    (char*)arg, strerror(status), status);
            return NULL;
        }

        printf("%s: Sleeping...\n");
        usleep(rand() % 100);
    }

    printf("%s: Exiting...\n");

    return NULL;
}

int main() {
    pthread_t  thread1, thread2, thread3, thread4;
    int        status;

    srand(time(NULL) ^ getpid());

    printf("Creating mutex...\n");
    if((status = pthread_mutex_init(&mutex, NULL)) != 0) {
        fprintf(stderr, "pthread_mutex_init() failed: %s (%d)", strerror(status), status);
        return 0;
    }

    printf("Creating threads...\n");
    if((status = pthread_create(&thread1, NULL, routine, "thread1")) != 0) {
        fprintf(stderr, "pthread_create(thread1) failed: %s (%d)", strerror(status), status);
        return 1;
    }
    if((status = pthread_create(&thread2, NULL, routine, "thread2")) != 0) {
        fprintf(stderr, "pthread_create(thread2) failed: %s (%d)", strerror(status), status);
        return 1;
    }
    if((status = pthread_create(&thread3, NULL, routine, "thread3")) != 0) {
        fprintf(stderr, "pthread_create(thread3) failed: %s (%d)", strerror(status), status);
        return 1;
    }
    if((status = pthread_create(&thread4, NULL, routine, "thread4")) != 0) {
        fprintf(stderr, "pthread_create(thread4) failed: %s (%d)", strerror(status), status);
        return 1;
    }

    printf("Joining threads...\n");
    if((status = pthread_join(thread1, NULL)) != 0) {
        fprintf(stderr, "pthread_join(thread1) failed: %s (%d)", strerror(status), status);
    }
    if((status = pthread_join(thread2, NULL)) != 0) {
        fprintf(stderr, "pthread_join(thread2) failed: %s (%d)", strerror(status), status);
    }
    if((status = pthread_join(thread3, NULL)) != 0) {
        fprintf(stderr, "pthread_join(thread3) failed: %s (%d)", strerror(status), status);
    }
    if((status = pthread_join(thread4, NULL)) != 0) {
        fprintf(stderr, "pthread_join(thread4) failed: %s (%d)", strerror(status), status);
    }

    printf("Main thread exiting (shared_var=%d)...\n", shared_var);
    return 0;
}

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
billtouchCommented:
One more point:

All shared variables need to be declared volatile. This causes the compiler to save each change to the varable so other threads can see the new value. The difference is that without the volatile notation, the compiler can optimize the code and keep the value in a register while it is using it and omit saving the value back to memory.

Bill
_mssAuthor Commented:
Two questions:
1. Lets say all threads have been created and therefore have called the "routine" function upon their creation. Is there a way to recall this function. For instance. Thread1 gets created and calls the function, then it changes the shared_var and exist the function. Thread 2 starts and does the same thing. Is there a way for thread 1 to call the function again?

2. Why do you join the threads with Null? Why not use the  pthread_exit command?

Thanks in advance.
Tim_UtschigCommented:
> 1. Lets say all threads have been created and therefore have called the "routine" function upon their creation.
> Is there a way to recall this function. For instance. Thread1 gets created and calls the function, then
> it changes the shared_var and exist the function. Thread 2 starts and does the same thing.
> Is there a way for thread 1 to call the function again?

When "routine" returns, the thread exits and is no more.  Would it have made more sense if I named it "run" ?
If you want to "restart" thread 1, well.. you can't.  Either create new thread or modify it so that it doesn't return.

> 2. Why do you join the threads with Null? Why not use the  pthread_exit command?

If you don't call pthread_join(), or otherwise do something that waits on the other threads to finish, then the program exits without any threads getting anything done.
_mssAuthor Commented:
I have one more question for all you geniuses.

I noticed that in Tim's solution, he has used mutexes to protect access to the shared_var.

What if I don't want that, meaning that I don't want this section to be protected. So the out put would be,

Thread 1 shared_var value = 1
Thread 2 shared_var value = 3
Thread 4 shared_var value = 4
Thread 3 shared_var value = 7

So basically the value for the shared value is still incrementing but sometimes multiple threads change this value without the printf actually printing the shared_var. Again this would be random. I mean I know I can put some rand function around printf clause and make it print depending on the out of the rand but is it possible to see a result such that shared_var change via multiple threads twice or three times even though one printf function gets executed.

Thanks in advance.

Tim_UtschigCommented:
I don't know about anyone else here, but I do not understand what it is you want to do.
_mssAuthor Commented:
Actually never mind. I got it working.

I basically wanted a create a bugie program where multiple thread get executed at the same time and change the shared_var at the same time in such a way that the output of the share_var would show something like 1, 4, 5, 7 .... where you don't see the values increment 1 by 1.

Anyway, I got it working by simply removing the mutexes and changing the usleep().

Many thanks
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.