Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pthread: one printf statement get printed twice in child thread

this is my first pthread program, and I have no idea why the printf statement get printed twice in child thread:

int x = 1;

void *func(void *p)
{
    x = x + 1;
    printf("tid %ld: x is %d\n", pthread_self(), x);
    return NULL;
}

int main(void)
{
    pthread_t tid;
    pthread_create(&tid, NULL, func, NULL);

    printf("main thread: %ld\n", pthread_self());

    func(NULL);
}

Observed output on my platform (Linux 3.2.0-32-generic #51-Ubuntu SMP x86_64 GNU/Linux):

1.
main thread: 140144423188224
tid 140144423188224: x is 2

2.
main thread: 140144423188224
tid 140144423188224: x is 3

3.
main thread: 139716926285568
tid 139716926285568: x is 2
tid 139716918028032: x is 3
tid 139716918028032: x is 3

4.
main thread: 139923881056000
tid 139923881056000: x is 3
tid 139923872798464tid 139923872798464: x is 2

for 3, two output lines from the child thread

for 4, the same as 3, and even the outputs are interleaved.

like image 844
chuchao333 Avatar asked Nov 25 '12 11:11

chuchao333


2 Answers

Threading generally occurs by time-division multiplexing. It is generally in-efficient for the processor to switch evenly between two threads, as this requires more effort and higher context switching. Typically what you'll find is a thread will execute several times before switching (as is the case with examples 3 and 4. The child thread executes more than once before it is finally terminated (because the main thread exited).

Example 2: I don't know why x is increased by the child thread while there is no output.

Consider this. Main thread executes. it calls the pthread and a new thread is created.The new child thread increments x. Before the child thread is able to complete the printf statement the main thread kicks in. All of a sudden it also increments x. The main thread is however also able to run the printf statement. Suddenly x is now equal to 3. The main thread now terminates (also causing the child 3 to exit). This is likely what happened in your case for example 2.

Examples 3 clearly shows that the variable x has been corrupted due to inefficient locking and stack data corruption!!

For more info on what a thread is.

Link 1 - Additional info about threading

Link 2 - Additional info about threading

Also what you'll find is that because you are using the global variable of x, access to this variable is shared amongst the threads. This is bad.. VERY VERY bad as threads accessing the same variable create race conditions and data corruption due to multiple read writes occurring on the same register for the variable x. It is for this reason that mutexes are used which essentially create a lock whilst variables are being updated to prevent multiple threads attempting to modify the same variable at the same time. Mutex locks will ensure that x is updated sequentially and not sporadically as in your case.

See this link for more about Pthreads in General and Mutex locking examples.
Pthreads and Mutex variables

Cheers,
Peter

like image 103
Peter H Avatar answered Sep 29 '22 10:09

Peter H


Hmm. your example uses the same "resources" from different threads. One resource is the variable x, the other one is the stdout-file. So you should use mutexes as shown down here. Also a pthread_join at the end waits for the other thread to finish its job. (Usually a good idea would also be to check the return-codes of all these pthread... calls)

#include <pthread.h>
#include <stdio.h>
int x = 1;
pthread_mutex_t mutex;

void *func(void *p)
{
    pthread_mutex_lock (&mutex);
    x = x + 1;
    printf("tid %ld: x is %d\n", pthread_self(), x);
    pthread_mutex_unlock (&mutex);
    return NULL;
}

int main(void)
{
    pthread_mutex_init(&mutex, 0);

    pthread_t tid;
    pthread_create(&tid, NULL, func, NULL);

    pthread_mutex_lock (&mutex);
    printf("main thread:  %ld\n", pthread_self());
    pthread_mutex_unlock (&mutex);

    func(NULL);
    pthread_join (tid, 0);
}
like image 42
pbhd Avatar answered Sep 29 '22 11:09

pbhd