pthread_join - pthread_create y pasando un entero como el último argumento
pthreads php (5)
Debería emitir la dirección de i
(en lugar del valor de i
como lo hace ahora) en el último argumento de pthread_create ().
pthread_create(&thread, 0, foo, (void *) &i);
^ is missing
Y el casting está mal en tu función también. Debería ser:
int a = *((int*) i);
- Si pretende leer el valor, también debe inicializar
i
con algún valor en main (), ya que no está inicializado ahora.
2 Usa la definición adecuada para main ():
int main(void)
o int main(int argc, char *argv[])
o su equivalente.
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 lanzamiento ( (void *) i
e int a = (int) i
). ¿Cómo puedo pasar un entero como el último argumento de pthread_create
correctamente?
Pregunta antigua, pero enfrenté el mismo problema hoy, y decidí no seguir este camino. Mi aplicación realmente tenía que ver con el rendimiento, así que elegí tener esta matriz de int
declarada estáticamente.
Como no conozco muchas aplicaciones en las que tu pthread_join
/ pthread_cancel
esté en un ámbito diferente al de tu pthread_create
, elegí esta manera:
#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]);
}
}
Me parece más elegante, más eficiente y no tiene que preocuparse por la liberación, ya que solo vive en este ámbito.
Puede asignar un int
en el montón y pasarlo a pthread_create()
. A continuación, puede desasignarlo en su función de hilo:
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);
}
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 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 en la actualidad la mayoría de los sistemas son nativos de 64 bits.
#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;
}
Sobre la base de la respuesta de szx (dale el crédito), he aquí cómo funcionaría en tu bucle for
:
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 la cosa que se pasa a pthread_create()
en cada iteración es diferente, por lo que ninguno de tus hilos termina intentando acceder a la misma memoria y no tiene ningún problema de seguridad de subprocesos como lo haría si acabara de pasar la dirección de i
. En este caso, también podría configurar una matriz y pasar las direcciones de los elementos.