Solving C Threads "Balance" Problem

  • Thread starter Thread starter James889
  • Start date Start date
  • Tags Tags
    Threads
AI Thread Summary
The issue with the final Balance remaining unchanged is due to incorrect function signatures in the thread routines and improper usage of pthread_create and pthread_join. The thread functions should return void* and accept a void* argument, which is essential for proper thread execution. Additionally, the thread creation and joining calls must not pass the address of the thread variable. Debugging techniques, such as adding print statements, can help confirm whether the thread functions are executing. Ensuring correct compilation with the pthread library and addressing warnings can resolve these issues effectively.
James889
Messages
190
Reaction score
1
Hi,

I've recently started C and i have a quick question

in the code below i increase the variable Balance in two threads, but somehow the final Balance is still equal to the initial value. Why?
Code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

int Balance = 100;

void *ThreadRoutine1(void) {

    pthread_mutex_lock(&mutex);
    Balance++;
    pthread_mutex_unlock(&mutex);
    printf("Balance is now:%d\n",Balance);
    pthread_exit(NULL);
}

void *ThreadRoutine2(void) {

        pthread_mutex_lock(&mutex);
        Balance++;
        pthread_mutex_unlock(&mutex);
        printf("Balance is now:%d\n",Balance);
        pthread_exit(NULL);

}

int main() {

        pthread_t thread1,thread2;
        int thread1_id;
        int thread2_id;        thread1_id = pthread_create(&thread1,NULL,(void *)ThreadRoutine1,NULL);
        thread2_id = pthread_create(&thread2,NULL,(void *)ThreadRoutine2,NULL);

        pthread_join(&thread1,NULL);
        pthread_join(&thread2,NULL);

        printf("Final Balance is:%d\t",Balance);
}
 
Physics news on Phys.org
Your pointers are out of whack. For example, your thread functions should return void (EDIT: that's badly put - let's say "should have a return type of void"), not void*. If a function requires a void*, then use the & operator.

And make sure you don't pass a pointer when the function doesn't expect one.

Anyways, note you aren't getting output from the printf's in your thread functions. They are not being run.

Define your thread functions like this:
Code:
void ThreadRoutine1(void) {

The creates should look like this:

Code:
        thread1_id = pthread_create(&thread1,NULL,(void *)&ThreadRoutine1,NULL);
        thread2_id = pthread_create(&thread2,NULL,(void *)&ThreadRoutine2,NULL);

And also your joins are wrong and should look like this:
Code:
        pthread_join(thread1,NULL);
        pthread_join(thread2,NULL);

In these kind of cases, pay a lot of attention to the warnings you're getting. Make sure you compile with -Wall to get all warnings. For example, you're missing the return at the end of main. So add 'return 0;' at the end of it.

After those fixes, it works and compiles without warnings for me. Hope that helps!
 
Last edited:
I never really understood (in my case) why you have to type cast the ThreadRoutine to void * when it already is of the type void *.
Code:
thread1_id = pthread_create(&thread1,NULL,(void *)&ThreadRoutine1,NULL);
thread2_id = pthread_create(&thread2,NULL,(void *)&ThreadRoutine2,NULL);
 
Grep said:
Your pointers are out of whack. For example, your thread functions should return void (EDIT: that's badly put - let's say "should have a return type of void"), not void*. If a function requires a void*, then use the & operator.
No, that's wrong. The function pointer passed into pthread_create is supposed to have type
void* (*)(void*)
That is, a pointer to a function that returns void* and takes as argument a void*. For example
Code:
void* myfunc(void *p)
{
  printf("In myfunc!");
  return NULL;
}

int main()
{
  pthread_t th;
  pthread_create(&th, NULL, &myfunc, NULL);
  pthread_join(th, NULL);
}

The return value of the function can be obtained when you invoke pthread_join.


Code:
        thread1_id = pthread_create(&thread1,NULL,(void *)&ThreadRoutine1,NULL);
        thread2_id = pthread_create(&thread2,NULL,(void *)&ThreadRoutine2,NULL);
Similarly, this is not the right way to do things. Any success you've had is due to the following three things:
  1. C allows implicit conversion from void* to other pointer types
  2. You weren't using C++ (which would complain about the conversion)
  3. You are fortunate enough to be running in an environment that doesn't crash your program when the pthread library invokes your function thinking it takes and returns a void*



Code:
 pthread_join(thread1,NULL);
This is right, though.
 
Last edited:
James889 said:
in the code below i increase the variable Balance in two threads, but somehow the final Balance is still equal to the initial value. Why?
Did you remember to link against the pthread library? e.g. in a unix system, this would usually require putting "-lpthread" on your link line.

Did you do any debugging? For example, putting a print statement in your functions (at the top!) to see if they're even getting that far?



Aside: the pthread library is not part of the C library, and there are other threading libraries available. Your thread would have been better named as something like "C pthreads question".

Another aside: pthread_create doesn't return a "thread identifier" like it appears you think it does. It returns whether or not there were any errors creating the thread. (the return value will be 0 if and only if there was no error)
 
Hurkyl said:
No, that's wrong. The function pointer passed into pthread_create is supposed to have type
void* (*)(void*)

Ouch, thanks for catching that, Hurkyl. Had to refresh my memory on pthreads (been using Qt and Boost threads). First tried to get the man page for pthread_create, but oddly, I don't have it. Then checked for an example with Google, and wouldn't you know the example was wrong (and the compiler silent :frown:). Man page would have given me the right signature. In short, I will now investigate why the darn man page is missing. That and be more careful with where I get my examples! Sheesh.
 
Back
Top