Как я могу изменить переменную структуры в функции с помощью потоков? - PullRequest
1 голос
/ 01 мая 2019

Я хочу изменить переменную struct в функции thread на global. Но это не работает.

#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);


}

Результат этого кода:

reservable: 0 reservable MAIN: 2

Но я хочу увидеть:

reservable: 2 reservable MAIN: 5

Ответы [ 2 ]

3 голосов
/ 01 мая 2019

Необходимо решить пару вопросов:

  1. У вас есть состояние гонки между main и рабочим потоком в структуре customer. Потоки врываются в одно и то же время, пытаясь получить доступ к полю reservable, и он не определяет, какой поток сделает его первым.

    Один из вариантов - заставить поток main дождаться завершения рабочего потока (используя pthread_join), прежде чем пытаться напечатать обновленное значение, или использовать условную конструкцию, например семафор, чтобы убедиться, что заказ (в зависимости от целей вашего приложения). Всегда detach или join ваши темы.

  2. customer уже является указателем, поэтому вы можете просто передать его в рабочую функцию как есть, не беря адрес с помощью &, что делает его тип Customer **. Если бы вы поместили customer в стек локальных функций, а не в кучу, было бы целесообразно использовать &.

... и несколько менее критичных предложений ...

  1. Не забудьте освободить память customer, чтобы избежать утечки.

  2. Возвращает значение void * из рабочей функции.

  3. abc - запутанное имя переменной - threads более точно. То же самое для t, rc и a.

  4. Нет необходимости для приведения возвращаемого значения malloc.

Вот обновленная версия:

#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;
}

Выход:

reservable 2
reservable MAIN 5
1 голос
/ 01 мая 2019

Когда вы создаете новый поток, он запускается независимо от основного потока.Это означает, что ничто не мешает выполнению printf in main до того, как CustomerFunc выполнит какое-либо изменение.

Простой способ исправить это - основной поток ждет, пока новый поток не завершит работу, вызвавpthread_join.

Вы также не передаете customer на pthread_create должным образом.&customer имеет тип Customer **, но ваша функция потока ожидает Customer *, поэтому удалите оператор адреса &.

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

printf("reservable MAIN%d", customer->reservable);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...