pthread crear y pasar un entero como último argumento


Tengo las siguientes funciones:

void *foo(void *i) {
    int a = (int) i;
}

int main() {
    pthread_t thread;
    int i;
    pthread_create(&thread, 0, foo, (void *) i);
}

En la compilación, hay algunos errores sobre el casting ((void *) i y int a = (int) i). ¿Cómo puedo pasar un entero como el último argumento de pthread_create correctamente?

 23
Author: jww, 2013-10-07

5 answers

Basándose en la respuesta de szx (así que dale el crédito), así es como funcionaría en tu for bucle:

void *foo(void *i) {
    int a = *((int *) i);
    free(i);
}

int main() {
    pthread_t thread;
    for ( int i = 0; i < 10; ++1 ) {
        int *arg = malloc(sizeof(*arg));
        if ( arg == NULL ) {
            fprintf(stderr, "Couldn't allocate memory for thread arg.\n");
            exit(EXIT_FAILURE);
        }

        *arg = i;
        pthread_create(&thread, 0, foo, arg);
    }

    /*  Wait for threads, etc  */

    return 0;
}

En cada iteración del bucle, estás asignando nueva memoria, cada una con una dirección diferente, por lo que lo que se pasa a pthread_create() en cada iteración es diferente, por lo que ninguno de tus subprocesos termina tratando de acceder a la misma memoria y no obtienes ningún problema de seguridad de subprocesos de la forma en que lo harías si acabas de pasar la dirección de i. En este caso, también podría configurar un array y pasa las direcciones de los elementos.

 28
Author: Paul Griffiths,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-08 00:05:41

Puede asignar un int en el montón y pasarlo a pthread_create(). Luego puede desasignar en su hilo de función:

void *foo(void *i) {
    int a = *((int *) i);
    free(i);
}

int main() {
    pthread_t thread;
    int *i = malloc(sizeof(*i));
    pthread_create(&thread, 0, foo, (void *) i);
}
 19
Author: szx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-07 19:31:22

Deberías convertir la dirección de i (en lugar del valor de i como lo haces ahora) en el último argumento de pthread_create().

pthread_create(&thread, 0, foo, (void *) &i);
                                         ^  is missing

Y el casting también está mal en tu función. Debe ser:

int a = *((int*) i);
  1. Si quieres leer el valor, también debes inicializar i a algún valor en main() ya que ahora no está inicializado.

2 Use la definición apropiada para main ():

 int main(void) 

O int main(int argc, char *argv[]) o su equivalente.

 11
Author: P.P.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-07 19:47:18

Vieja pregunta, pero me enfrenté al mismo problema hoy, y decidí no seguir este camino. Mi aplicación era realmente sobre el rendimiento, así que elegí tener este array de ints declarado estáticamente.

Ya que no conozco un montón de aplicaciones donde su pthread_join / pthread_cancel está en otro ámbito que su pthread_create, elegí este camino:

#define NB_THREADS 4

void *job(void *_i) {
  unsigned int i = *((unsigned int *) _i);
}

int main () {
  unsigned int ints[NB_THREADS];
  pthread_t    threads[NB_THREADS];
  for (unsigned int i = 0; i < NB_THREADS; ++i) {
    ints[i] = i;
    pthread_create(&threads[i], NULL, job, &ints[i]);
  }
}

Lo encuentro más elegante, más eficiente, y no tienes que preocuparte por liberarte ya que solo vive en este ámbito.

 6
Author: Jerska,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-16 22:22:50

Si bien esta es una pregunta antigua, falta una opción cuando todo lo que necesita es pasar un entero positivo como un descriptor: puede pasarlo directamente como la dirección, mientras que es un truco funciona bien y evita asignar nada :)

NOTA: el tamaño del entero debe coincidir con el tamaño de un puntero en su sistema operativo, pero hoy en día la mayoría de los sistemas son 64bits nativos.

#include <pthread.h>
#include <inttypes.h>
#include <stdio.h>

void *_thread_loop(void *p)
{
  uint64_t n = (uint64_t)p;

  printf("received %llu\n", n);

  return NULL;
}



int main(int argc, char const *argv[])
{
  pthread_t read_thread_id;
  uint64_t n = 42;
  pthread_create(&read_thread_id, NULL, _thread_loop, (void *)n);

  pthread_join(read_thread_id, NULL);
  return 0;
}
 0
Author: Schmurfy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-16 07:30:27