如何将int作为“ void *”传递给线程启动函数?

时间:2018-11-23 02:00:24

标签: c casting int pthreads void

我本来是斐波那契变量数组的全局变量,但发现这是不允许的。我需要进行基本的多线程处理并处理竞争条件,但是我无法克服在pthread create中将int作为void参数的问题。我尝试使用没有运气的常量指针。出于某些奇怪的原因,void *通过了第一个布尔测试,但在以下情况下没有通过其他测试:

  $ 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.

我的代码一团糟,我真的很困惑,因为我已经重写了很多次了。如果将线程运行函数中的所有args转换为int,则会得到分段错误11,这很有意义。通过地址传递i索引并对其取消引用的所有尝试均以失败告终,因为它是空值,不能用作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;
}

3 个答案:

答案 0 :(得分:5)

您无需在对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的指针意味着一切不受控制。

答案 1 :(得分: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的答案可以避免此问题。

答案 2 :(得分:0)

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