Как передать int как "void *" в функцию запуска потока? - PullRequest
0 голосов
/ 23 ноября 2018

У меня изначально была глобальная переменная для моего массива переменных Фибоначчи, но выяснилось, что это не разрешено.Мне нужно сделать элементарную многопоточность и обработать условия гонки, но я не могу передать подачу int как пустой аргумент в pthread create.Я попытался использовать постоянный указатель без удачи.По какой-то странной причине 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.

Мой код - беспорядок, и я очень запутался, потому что переписывал его много раз.Если я приведу все аргументы в моей функции запуска потока как целые, я получу ошибку сегментации 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 голосов
/ 23 ноября 2018

В функции run() вы должны выполнить:

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

, а в остальном run() вам не нужно разыгрывать arg.Замените (int)arg на arg.

РЕДАКТИРОВАТЬ:
То, как вы передаете аргумент fun() при создании потоков, может вызвать условие гонки , поскольку все потоки будут использоватьтот же указатель.Проверьте ответ @ Jonathan, чтобы избежать этой проблемы.

0 голосов
/ 23 ноября 2018

Вам не нужно приводить при вызове 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 означает, что все неуправляемо.

0 голосов
/ 23 ноября 2018

@ efuddy.Вместо (int)arg вы должны использовать (int *)arg для правильного приведения ** пустого указателя * void *arg

...