CUESTIÓN

Esto de los hilos no funciona ni para atrás. Con lo bien que estaba yo con el UNIX de mis entretelas. Aquí está el código:
    [...]
    caracter = '-';
    lpThreadHnd[0] = CreateThread(NULL, 0, imprimir, (void*)&caracter, 0,
                                  lpThreadId);
    if(lpThreadHnd[0] == NULL)
    {
        PERROR("CreateThread");
        return 1;
    }

    caracter = '+';
    lpThreadHnd[1] = CreateThread(NULL, 0, imprimir,
                                  (void*)&caracter, 0,
                                  lpThreadId + 1);
    [...] 
He hecho el programa, y hay algunos hilos que simplemente no imprimen nada. ¨Qué puede estar pasando?


SOLUCIÓN

A este error, por lo común que es, hay que prestarle atención. Surge cuando queremos pasarle diferentes argumentos a varios hilos y se nos ocurre la feliz idea de economizar bits y reusar la misma variable para pasar los argumentos a los hilos. En el caso del ejemplo, la variable caracter se usa para pasar un '-' al primer hilo y un '+' al segundo. Por deformación de la programación secuencial, tendemos a pensar que cuando se crea un hilo, se "salta" a la función del hilo y esto no es así. Cuando se crea un hilo nuevo, otra instancia de ejecución comienza a existir y se ejecutará "en paralelo" con el hilo que lo creó. Tan en paralelo como pueden ejecutarse las cosas con una sola CPU, no obstante.

Lo que en realidad ocurre es lo siguiente:
  1. En la variable caracter almacenamos un '-'.
  2. A la función del hilo le pasamos la dirección de la variable caracter, pero la función del hilo ni siquiera comienza a ejecutarse porque aún no ha conseguido la CPU.
  3. Ponemos un '+' en caracter que sobreescribirá el menos anterior, como es natural. Pero observad que el primer hilo lo que tiene es un puntero, con lo que la trampa ya se fraguó.
  4. Creamos el segundo hilo.
  5. Posteriormente, cuando el primer hilo consiga la CPU y mire lo que hay en el puntero que le hemos pasado, verá que hay un '+' y no el '-' que debería haber.
A la vista de todo esto, ¿no hubiera sido mejor que CreateThread hubiera sido diseñada para que admitiera un valor en lugar de una referencia? Pues no. Pasando una referencia tenemos mayor flexibilidad. Podemos pasar cualquier objeto a la función del hilo. Incluso podemos pasar varios parámetros. Para ello, declaramos una estructura con los parámetros que deseamos pasar y damos un puntero a esa estructura a CreateThread. La función del hilo recupera los parámetros con un sencillo casting al tipo de la estructura.


© 2003 Guillermo González Talaván.