【问题标题】:How to pass an int as "void *" to thread start function?如何将 int 作为“void *”传递给线程启动函数?
【发布时间】:2019-04-25 15:52:41
【问题描述】:

我最初为我的斐波那契变量数组设置了一个全局变量,但发现这是不允许的。我需要进行基本的多线程处理并处理竞争条件,但我无法在 pthread create 中将 int 作为 void 参数提供。我试过使用一个没有运气的常量指针。出于某种奇怪的原因,void* 通过了第一个布尔测试,但没有通过 else if:

  $ gcc -o fibonacci fibonacci.c
    fibonacci.c:22:16: warning: comparison between pointer and integer ('void *' and 'int')
      else if (arg == 1)
               ~~~ ^  ~
    1 warning generated.

我的代码一团糟,我真的很困惑,因为我已经重写了很多次。如果我将线程运行函数中的所有参数转换为整数,我会得到一个分段错误 11,这是有道理的。所有通过地址传递 i 索引并取消引用它的尝试都失败了,因为它是一个 void 并且不能用作 int。你能推荐点别的吗?

#include<stdio.h> //for printf
#include<stdlib.h>  //for malloc
#include<pthread.h> //for threading

#define SIZE 25 //number of fibonaccis to be computed
int *fibResults;  //array to store fibonacci results

void *run(void *arg)  //executes and exits each thread
{
  if (arg == 0)
  {
    fibResults[(int)arg] = 0;
    printf("The fibonacci of %d= %d\n", (int)arg, fibResults[(int)arg]);    
    pthread_exit(0); 
 }

  else if (arg == 1)
  {
    fibResults[(int)arg] = 1;
    printf("The fibonacci of %d= %d\n", (int)arg, fibResults[(int)arg]);   
    pthread_exit(0);  
  }
  else
  {
    fibResults[(int)arg] = fibResults[(int)arg -1] + fibResults[(int)arg -2];
    printf("The fibonacci of %d= %d\n", (int)arg, fibResults[(int)arg]);
    pthread_exit(0);
  }
}

//main function that drives the program.
int main()
{
  pthread_attr_t a;
  fibResults = (int*)malloc (SIZE * sizeof(int));
  pthread_attr_init(&a);  

  for (int i = 0; i < SIZE; i++)
  {
    pthread_t thread;
    pthread_create(&thread, &a, run,(void*) &i);
    printf("Thread[%d] created\t", i); 
    fflush(stdout);
    pthread_join(thread, NULL);
    printf("Thread[%d] joined & exited\t", i); 
  }
  return 0;
}

【问题讨论】:

    标签: c casting int pthreads void


    【解决方案1】:

    run() 函数中你应该这样做:

    void *run(void *ptrarg)  //executes and exits each thread
    {
      int arg = *((int *)ptrarg);
      if (arg == 0)
      ....
      ....
    

    run() 的其余部分,您不需要转换 arg。将(int)arg 替换为arg

    编辑:
    在创建线程时将参数传递给fun() 的方式可能会导致race condition,因为所有线程都将使用相同的指针。检查@Jonathan 的回答以避免此问题。

    【讨论】:

    • 这是错误的。 OP 错误地传递了i 的地址而不是值,这会产生数据竞争。
    • @R.. 当然,在这种特殊情况下,由于竞争情况,这不是理想的方式。但这并没有错。
    【解决方案2】:

    您不需要在调用 pthread_create() 时进行强制转换 - 到 void * 的转换是自动的。

    在线程函数中,你可以使用

    int i = *(int *)arg;
    

    但是,您现在遇到了同步问题;所有线程都使用相同的(指向相同的)整数变量,并且由于调度问题,您无法预测它们将看到哪个值。每个线程的数据需要是“每个线程”。

    因此,有多种解决方法。在这种情况下,我可能会使用

    #include <stdint.h>
    

    main():

        pthread_create(&thread, &a, run, (void*)(uintptr_t)i);
    

    然后在线程函数中:

    int i = (uintptr_t)arg;
    

    现在演员——甚至双重演员——是必要的。转换为uintptr_t 确保整数值足够大以容纳指针;需要转换为void *,因为没有从任何整数类型到void * 的隐式转换。这确保每个线程函数调用具有不同的值。共享指向int 的指针意味着一切都不受控制。

    【讨论】:

      【解决方案3】:

      @efuddy。而不是(int)arg,您应该使用(int *)arg 正确转换**void 指针* void *arg

      【讨论】:

      • eapetcho,感谢您的快速回复。现在我得到:错误:数组下标不是整数 fibResults[(int *)arg] = 0;
      猜你喜欢
      • 2021-11-19
      • 2022-11-25
      • 2021-02-27
      • 2020-11-14
      • 1970-01-01
      • 2013-01-27
      • 2012-11-08
      • 1970-01-01
      • 2013-10-29
      相关资源
      最近更新 更多