Pregunta

Estoy aprendiendo sobre los hilos POSIX en este momento, pero supongo que esto es solo una pregunta general sobre multihilo, por lo que espero que alguien pueda ayudarme. Tengo un ejemplo del libro en el que estoy trabajando que demuestra una condición de carrera:

void *thread_main(void *thread_number) {
    printf("In thread number %d.\n", *(int *)thread_number);
}

void main() {
    int i = 0;
    pthread_t thread;

    for( i = 0; i < 10; i++ ) {
        printf("Creating thread %d.\n");
        pthread_create(&thread, 0, thread_main, &i);
        printf("Created thread %d.\n");
    }
}

Hay algunas cosas que no entiendo de esto. Primero, " En el número de hilo 5. " se imprime muchas veces aunque no se supone que esté en el hilo número 5. En el libro, el ejemplo muestra que el hilo 8 se imprime muchas veces. Tampoco entiendo la parte que dice * (int *) thread_number . Intenté cambiar esto a solo thread_number, pero eso me dio números extraños una y otra vez.

El libro realmente no explica esto. ¿Alguien me puede dar una explicación clara de lo que está pasando aquí? No entiendo por qué no imprime algo como:

> Creating thread 1.
> In thread number 1.
> Created thread 1.
> Creating thread 2.
> In thread number 2.
> Created thread 2.

Lo sé porque es multiproceso el " En el hilo número x. " la parte vendrá en diferentes momentos, pero realmente no entiendo por qué no hay exactamente 10 '' en el hilo número x '' ¡con una línea por cada hilo que creé!

~ desi

¿Fue útil?

Solución

En primer lugar, el * (int *) thread_number es un elemento de puntero; cuando acaba de tener thread_number, los 'números extraños' eran las direcciones de puntero a la 'i' desde la función main (y a menos que yo estoy equivocado, todos deberían haber sido el mismo número para una sola ejecución del programa (por lo que cada uno de los 10 hilos debería haber tenido el mismo " En el número de hilo [número] ")).

Debe comprender que estos eran punteros para que los 5 repetidos tuvieran sentido: cada subproceso funcionaba con el mismo i subyacente de la función principal , no se estaba copiando para cada nuevo subproceso , por lo que cuando el i se estaba incrementando en la función principal , eso se reflejó para el thread_number en la función thread_main .

La pieza final del rompecabezas es que el tiempo de configuración para cada hilo nuevo y luego el cambio de contexto (cambiar qué hilo se está ejecutando realmente) no es inmediato, por lo que en su caso el bucle for se ejecuta 5 veces antes que los hilos recién creados en realidad se ejecutan (y en el caso del libro, el ciclo for se ejecuta 8 veces antes del cambio de contexto), luego cada uno de los hilos mira el mismo valor i subyacente que ahora es 5.

Otros consejos

Es posible que el bucle for pueda iterar 10 veces antes de que cualquiera de los 10 subprocesos creados tenga la oportunidad de ejecutarse. En ese caso, el valor de * thread_number sería 10 para cada hilo (ya que es un puntero a una única ubicación de memoria con un solo valor).

Si no pasa un puntero a i a pthread_create , entonces el valor de int termina siendo tratado como una dirección , por lo tanto, cuando lo eliminas en thread_main , estás accediendo a alguna ubicación de memoria arbitraria, cuyo contenido probablemente no esté definido. Tienes suerte de no estar segfaulting en ese caso.

Si desea ver el valor correcto para * thread_number en cada hilo, debería malloc un nuevo int antes de llamar a < code> pthread_create y asígnele el valor actual de i , así:

for( i = 0; i < 10; i++ ) {
    int *thread_count = malloc(sizeof(int));
    *thread_count = i;
    printf("Creating thread %d.\n", i);
    pthread_create(&thread, 0, thread_main, thread_count);
    printf("Created thread %d.\n", i);
}

Por supuesto, entonces deberías liberar la memoria cuando el hilo haya terminado con ella, así:

void *thread_main(void *thread_number) {
    printf("In thread number %d.\n", *(int *)thread_number);
    free(thread_numbr);
}

Primero, una condición de carrera es algo malo. Este programa no debería funcionar como espera. Una condición de carrera significa que el programa está diseñado para romperse.

En este caso, parece que todos tus hilos están compartiendo la variable i . Les estás pasando referencias a una única variable compartida, que intentan informar cada vez que se programan.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top