【问题标题】:How can I change a struct variable in a function using threads?如何使用线程更改函数中的结构变量?
【发布时间】:2019-05-01 15:34:45
【问题描述】:

我想把线程函数中的struct变量改成全局变量。

但这不起作用:

#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

【问题讨论】:

  • (void *)&amp;customer 是一个指向指针的指针。
  • 另外,CustomerFunc 应该返回一个值。
  • 另外,您应该等待线程完成后再尝试打印结果。
  • 但我不希望这个函数返回值@JohnnyMopp
  • 函数原型说它应该返回一个void *。如果您不想返回任何内容,请更改为void CustomerFunc(void *customer) {

标签: c multithreading struct


【解决方案1】:

有几个问题需要解决:

  1. maincustomer 结构上的工作线程之间有一个 race condition。线程同时涌入并试图访问reservable 字段,并且不确定哪个线程首先到达那里。

    一种选择是让main 线程等待工作线程完成(使用pthread_join),然后再尝试打印更新的值,或者使用信号量等条件构造来确保排序(取决于您的应用程序目标)。总是detachjoin 你的线程。

  2. customer 已经是一个指针,所以你可以直接将它传递给工作函数,而无需使用&amp; 获取地址,这使得它的类型为Customer **。如果您在本地函数堆栈而不是堆上分配了customer,那么使用&amp; 是合适的。

...以及一些不太重要的建议...

  1. 记得释放customer 的内存以避免泄漏。
  2. 从工作函数返回 void * 值。
  3. abc 是一个容易混淆的变量名——threads 更准确。 trca 也是如此。
  4. No need 转换 malloc 的返回值。
  5. 检查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

【讨论】:

  • Re, "...您也可以为此使用互斥锁..." 这听起来好像使用互斥锁会以某种方式确保线程以正确的顺序访问变量。但是单独的互斥锁永远无法做到这一点。将共享变量访问包装在互斥锁中将确保两个线程看到共享数据的一致视图,但程序的结果仍然取决于竞争:这将取决于哪个线程赢得了锁定互斥锁的竞争。
  • 这很好,互斥锁不能确保没有条件变量或信号量的排序。已更正。
【解决方案2】:

当您创建一个新线程时,它会独立于主线程运行。这意味着在CustomerFunc 进行任何更改之前,没有什么可以阻止main 中的printf 执行。

解决此问题的一种简单方法是让主线程通过调用pthread_join 等待新线程完成。

您也没有正确地将customer 传递给pthread_create&amp;customer 的类型为 Customer **,但您的线程函数需要 Customer *,因此请删除地址运算符 &amp;

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

printf("reservable MAIN%d", customer->reservable);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-05
    • 2022-08-23
    • 1970-01-01
    • 2011-05-19
    • 1970-01-01
    • 2021-07-31
    • 2020-09-04
    • 2023-03-24
    相关资源
    最近更新 更多