1

I want to change the struct variable in the thread function as global.

But this doesn't work:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 1

typedef struct {
  int id;
  int reservable;
} Customer;

void *CustomerFunc(void *customer) {
  Customer *a;
  a = (Customer *)customer;
  printf("reservable %d", a->reservable);
  a->reservable = 5;
}

int main (int argc, char *argv[]) {
  pthread_t abc[NUM_THREADS];
  int rc; 
  long t;
  Customer *customer = (Customer*)malloc(sizeof(Customer));
  customer->id = 1;
  customer->reservable = 2;
  rc = pthread_create(&abc[0], NULL, CustomerFunc, (void *)&customer);
  printf("reservable MAIN%d", customer->reservable);
  pthread_exit(NULL);
}

This code result is:

reservable: 0 reservable MAIN: 2

But I want to see:

reservable: 2 reservable MAIN: 5
ggorlen
  • 44,755
  • 7
  • 76
  • 106
Sevval Kahraman
  • 1,185
  • 3
  • 10
  • 37

2 Answers2

4

There are a couple issues to resolve:

  1. You have a race condition between the main and the worker thread on the customer struct. The threads rush in at the same time trying to access the reservable field and it's non-deterministic as to which thread makes it there first.

    One option is to make the main thread wait for the worker thread to finish (using pthread_join) before attempting to print the updated value, or use a conditional construct like a semaphore to ensure ordering (depending on your application goals). Always detach or join your threads.

  2. customer is already a pointer, so you can just pass it into the worker function as-is, without taking the address using &, which makes its type Customer **. Had you allocated customer on the local function stack rather than the heap, it'd be appropriate to use &.

...and a few less critical suggestions...

  1. Remember to free customer's memory to avoid a leak.
  2. Return a void * value from the worker function.
  3. abc is a confusing variable name--threads is more accurate. Same for t, rc and a.
  4. No need to cast the return value of malloc.
  5. Check the return value of malloc (skipped in my code below for brevity).

Here's an updated version:

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

#define NUM_THREADS 1

typedef struct {
    int id;
    int reservable;
} Customer;

void *customerFunc(void *arg) {
    Customer *customer = (Customer *)arg;
    printf("reservable %d\n", customer->reservable);
    customer->reservable = 5;
    return NULL;
}

int main(int argc, char *argv[]) {
    pthread_t threads[NUM_THREADS];
    Customer *customer = malloc(sizeof(*customer));
    customer->id = 1;
    customer->reservable = 2;

    pthread_create(&threads[0], NULL, customerFunc, customer);
    pthread_join(threads[0], NULL);

    printf("reservable MAIN %d\n", customer->reservable);
    free(customer);
    return 0;
}

Output:

reservable 2
reservable MAIN 5
ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • Re, "...You could also use a mutex lock for this..." That makes it sound as if using the mutex would somehow ensure that the threads access the variable in the right order. But a mutex alone can never do that. Wrapping the shared variable access in a mutex would ensure that both threads see a consistent view of the shared data, but the outcome of the program still would depend on a race: It would depend on which thread won the race to lock the mutex. – Solomon Slow May 01 '19 at 17:06
  • That's a good point, mutex isn't going to ensure ordering without a condition variable or semaphore. Corrected. – ggorlen May 01 '19 at 17:32
1

When you create a new thread, it runs independently of the main thread. This means that nothing is stopping the printf in main from executing before CustomerFunc makes any change.

A simple way to fix this is for the main thread to wait until the new thread finishes by calling pthread_join.

You're also not passing customer to pthread_create properly. &customer has type Customer ** but your thread function is expecting a Customer *, so remove the address-of operator &.

rc = pthread_create(&abc[0],NULL,CustomerFunc, customer);
pthread_join(abc[0], NULL);

printf("reservable MAIN%d", customer->reservable);
dbush
  • 205,898
  • 23
  • 218
  • 273