Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using of shared variable by 10 pthreads

The problem is in following:

I want to write a short program that creates 10 threads and each prints a tread "id" that is passed to thread function by pointer.

Full code of the program is below:

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

struct params {
        pthread_mutex_t mutex;
        int id;
};

typedef struct params params_t;

void* hello(void* arg){
    int id;
    pthread_mutex_lock(&(*(params_t*)(arg)).mutex);
    id = (*(params_t*)(arg)).id;
    pthread_mutex_unlock(&(*(params_t*)(arg)).mutex);
    printf("Hello from %d\n", id);
}


int main() {
    pthread_t threads[10];
    params_t params;
    pthread_mutex_init (&params.mutex , NULL);

    int i;
    for(i = 0; i < 10; i++) {
            params.id = i;
            if(pthread_create(&threads[i], NULL, hello, &params));
    }

    for(i = 0; i < 10; i++) {
            pthread_join(threads[i], NULL);
    }

    return 0;
}

The supposed output is (not necessary in this order):

Hello from 0
....
Hello from 9

Actual result is:

Hello from 2
Hello from 3
Hello from 3
Hello from 4
Hello from 5
Hello from 6
Hello from 8
Hello from 9
Hello from 9
Hello from 9

I tried to place mutex in different places in hello() function, but it didn't help.

How should I implement thread sync?

EDIT: Supposed result is not necessary 0...9 it can be any combination of these numbers, but each one should appear only one time.

like image 346
Alex Avatar asked Jun 04 '12 09:06

Alex


People also ask

Do pthreads share variables?

They share a single foo variable. Global variable always exists only once per process and is usually protected by mutex to avoid concurrent access.

How do I share a variable between two threads?

You should use volatile keyword to keep the variable updated among all threads. Using volatile is yet another way (like synchronized, atomic wrapper) of making class thread safe. Thread safe means that a method or class instance can be used by multiple threads at the same time without any problem.

What are pthreads used for?

POSIX Threads, commonly known as pthreads, is an execution model that exists independently from a language, as well as a parallel execution model. It allows a program to control multiple different flows of work that overlap in time.

Does pthreads share heap?

It is important to distinguish between these two types of process memory because each thread will have its own stack, but all the threads in a process will share the heap. Threads are sometimes called lightweight processes because they have their own stack but can access shared data.


1 Answers

The problem lies in the below code:

for(i = 0; i < 10; i++) 
{             
  params.id = i;             
 if(pthread_create(&threads[i], NULL, hello, &params));     
} 

Your params.id value keeps getting updated in the main thread, whereas you are passing the same pointer to all the threads.

Please create seperate memory for params by dynamically allocating it and pass it to different threads to solve the problem.

EDIT1: Your usage of mutex to protect is also an incorrect idea. Though your mutex if used in main while setting the id also, may make the updation mutually exclusive, but you may not get your desired output. Instead of getting values from 0 .. 9 in different threads, you may get all 9s or still multiple threads may print same values.

So, using thread synchronization is not such a good idea for the output which you are expecting. If you still need to use one param variable between all threads and get output as 0 to 9 from each of the threads, better move the pthread_join into the first loop. This will ensure that each thread gets created, prints the value and then returns before the main spawns the next thread. In this case, you don't need the mutex also.

EDIT2: As for the updated question, where it is asked that it is not necessary to print the numbers 0..9 in a sequence, the printing can be random, but only once, the problem still remains the same more or less.

Now, let's say, the value of params.id is first 0 and thread 0 got created, now, thread 0 must print it before it is updated in the main thread, else, when thread 0 accessess it, the value of params.id would have become 1 and you will never get your unique set of values. So, how to ensure that thread 0 prints it before it is updated in main, Two ways for it:

  • Ensure thread 0 completes execution and printing before main updates the value
  • Use condition variables & signalling to ensure that main thread waits for thread 0 to complete printing before it updates the value (Refer to Arjun's answer below for more details)

In my honest opinion, you have selected the wrong problem for learning synchronization & shared memory. You can try this with some good problems like "Producer-Consumer", where you really need synchronization for things to work.

like image 120
Jay Avatar answered Sep 29 '22 00:09

Jay