Sean C
Sean C

Reputation: 83

C:multithreading- Parent thread exits before output

Update included after the first block of code

I am new to multithreading and am having an issue outputting the results of various threads in a C program. Specifically, I am attempting to output the average, maximum, and minimum within an array of integers to the user using a different thread for each. However, the parent thread which is supposed to print the three values terminates upon completion of the its children threads.

For the sake of testing, I currently print the results within the children thread, but I need to print these values in the parent thread. The code is as follows:

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


void *avgThread(int *nums,int*out)
{
    //sleep(1);
    int total = 0,x,avg;
    for(x=0;x<7;x++) total+=nums[x];
    avg = total/7;
    *out = avg;
    printf("%d\n",avg);
}

void *minThread(int *nums,int*out)
{
    int min = nums[0],x;
    for(x=1;x<7;x++)  if(nums[x]<min) min=nums[x];
     *out = min;
    printf("%d\n",min);

}

void *maxThread(int *nums,int*out)
{
    int max = nums[0],x;
    for(x=1;x<7;x++) if(nums[x]>max) max=nums[x];
    *out = max;
    printf("%d\n",max);

}

void *parentThread(int*nums)
{
    int average,minimum,maximum;
    pthread_t avg,min,max;
    pthread_attr_t avgfun,minfun,maxfun;

    pthread_attr_init(&avgfun);
    pthread_attr_init(&minfun);
    pthread_attr_init(&maxfun);

    pthread_create(&avg, &avgfun, avgThread(nums,&average), NULL);
    pthread_create(&min, &minfun, minThread(nums,&minimum), NULL);
    pthread_create(&max, &maxfun, maxThread(nums,&maximum), NULL);

    pthread_join(avg, NULL);
    pthread_join(min, NULL);
    pthread_join(max, NULL);

    printf("%d\n",maximum);
    printf("%d\n",average);
    printf("%d\n",minimum);
    pthread_join(pthread_self(),NULL);

    return NULL;
}

int main()
{
    int nums[] = {90, 81, 78, 95, 79, 72, 85};
    pthread_t prnt;
    pthread_attr_t parent;
    pthread_attr_init(&parent);
    pthread_create(&prnt,&parent,parentThread(nums),NULL);
    pthread_join(prnt,NULL);
    sleep(3);

    exit(0);
}

Update

Thank you to Pavel and others for pointing out some things I am doing wrong. I have made the necessary modifications to the thread initialization and call. I am also able to output the calculated average, max, and min in the parent thread, but only by making said variables global in scope. If anyone can tell me if I can keep:

int average,maximum,minimum

inside *parentThread and still calculate them inside the child threads, that would be great. Here is my code as it stands now:

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

int average,minimum,maximum;

void *avgThread(void *numsptr)
{
    sleep(1);
   int *nums=(int*)numsptr;

    int total = 0,x;
   for(x=0;x<7;x++) total+=(int)nums[x];
   average = total/7;
    return NULL;
}

void *minThread(void *numsptr)
{
    sleep(2);
    int *nums=(int*)numsptr,x;
    minimum = nums[0];
    for(x=1;x<7;x++)  if((int)nums[x]<minimum) minimum=(int)nums[x];
    return NULL;
}

void *maxThread(void *numsptr)
{
    sleep(3);
    int *nums=(int*)numsptr,x;

    maximum = nums[0];
    for(x=1;x<7;x++) if((int)nums[x]>maximum) maximum=(int)nums[x];
    return NULL;
}

void *parentThread(void *numsptr){
    int *nums=(int*)numsptr;
    //int average,minimum,maximum;
    pthread_t avg,min,max;
    pthread_attr_t avgfun,minfun,maxfun;

    pthread_attr_init(&avgfun);
    pthread_attr_init(&minfun);
    pthread_attr_init(&maxfun);

    pthread_create(&avg, &avgfun, &avgThread,(void*)nums);
    pthread_create(&min, &minfun, &minThread,(void*)nums);
    pthread_create(&max, &maxfun, &maxThread,(void*)nums);

    pthread_join(avg, NULL);
    printf("The average value is %d\n",average);
    pthread_join(min, NULL);
    printf("The minimum value is %d\n",minimum);
    pthread_join(max, NULL);
    printf("The max value is %d\n",maximum);

    return NULL;
}

int main()
{
   int nums[] = {90, 81, 78, 95, 79, 72, 85};
    pthread_t prnt;
    pthread_attr_t parent;
    pthread_attr_init(&parent);
    pthread_create(&prnt,&parent,&parentThread,(void*)nums);
    pthread_join(prnt,NULL);

    exit(0);
}

Upvotes: 0

Views: 59

Answers (1)

Pavel P
Pavel P

Reputation: 16843

You do not start threads properly. You have to pass function that will execute, but you are actually calling your function and passing its return value to pthread_create:

// call parentThread(nums) and then create thread.
pthread_create(&prnt, &parent, parentThread(nums),NULL);

What you wanted to do is this:

void *parentThread(void *nums_ptr)
{
    int *nums = (int*)nums_ptr;
    ...
    return NULL;
}

int main()
{
    int nums[] = {90, 81, 78, 95, 79, 72, 85};
    pthread_t prnt;
    pthread_create(&prnt, NULL, &parentThread, (void*)nums);
    ...
}

Same applies for all your other threads. Other issues that you have:

  • your thread function (that pthreads expect) should take a void pointer and return void pointer. E.g.: void *threadFunc(void *nums)
  • your function should return something (e.g. return NULL;)
  • you shouldn't try to joint your own thread: pthread_join(pthread_self(),NULL);

If anyone can tell me if I can keep: int average,maximum,minimum inside *parentThread and still calculate them inside the child threads

Sure you can do that. Define some struct that stores all that data and pass pointer to that data to your threads:

struct myState
{
    int average, minimum, maximum;
    int *nums
};

void *avgThread(void *data)
{
    sleep(1);
    myState *state = (myState*)data;

    int total = 0,x;
    for(int x=0; x<7; x++)
        total += state->nums[x];
    state->average = total/7;
    return NULL;
}

void *parentThread(void *nums_ptr)
{
    int *nums = (int*)nums_ptr;
    myState state;
    state.nums = nums;
    ...
    pthread_create(&avg, &avgfun, &avgThread, &state);
    ...
    pthread_join(avg, NULL);
    printf("The average value is %d\n", state.average);
    ...
    return NULL;
}

Upvotes: 2

Related Questions