que pthread_t pthread_join pthread_create pthread para libreria hilos hace funciones ejercicios ejemplos c++ multithreading boost-thread

pthread_t - C++ Pregunta de hilo: estableciendo un valor para indicar que el hilo ha terminado



pthread_join que hace (5)

¿Es seguro lo siguiente?

Soy nuevo en threading y deseo delegar un proceso lento en un hilo separado en mi programa C ++. Usando las bibliotecas de impulso, he escrito un código como este:

thrd = new boost :: thread (boost :: bind (& myclass :: mymethod, this, y finished_flag);

Donde finished_flag es un miembro booleano de mi clase. Cuando termina el hilo, establece el valor y el ciclo principal de mi programa comprueba si hay algún cambio en ese valor. Supongo que esto está bien porque solo comienzo un hilo, y ese hilo es lo único que cambia el valor (excepto cuando se inicializa antes de iniciar el hilo) Entonces, ¿está bien, o me estoy perdiendo algo, y necesita usar bloqueos y mutexes, etc.


Nunca mencionaste el tipo de finished_flag ...

Si es un bool recto, entonces podría funcionar, pero es una mala práctica, por varias razones. Primero, algunos compiladores almacenarán en caché las lecturas de la variable finished_flag , ya que el compilador no siempre capta el hecho de que otro subproceso lo está escribiendo. Puede evitar esto declarando al bool volátil , pero eso nos lleva en la dirección incorrecta. Incluso si las lecturas y escrituras están sucediendo como era de esperar, no hay nada que impida que el planificador del sistema operativo entrelaje los dos hilos a la mitad de una lectura / escritura. Eso podría no ser un problema aquí donde tienes una operación de lectura y otra de escritura en hilos separados, pero es una buena idea comenzar como quieres continuar.

Si, por otro lado, es un tipo seguro para subprocesos, como un CEvent en MFC (o equivalente en refuerzo ), entonces debería estar bien. Este es el mejor enfoque: use objetos de sincronización seguros para subprocesos para la comunicación entre hilos, incluso para indicadores simples.


En lugar de usar una variable miembro para indicar que el hilo está hecho, ¿por qué no usar una condition ? Ya está utilizando las bibliotecas de impulso, y la condition es parte de la biblioteca de hilos.

Compruébalo. Permite que el hilo del trabajador ''señalice'' que ha terminado, y el hilo principal puede verificar durante la ejecución si la condición ha sido señalada y luego hacer todo lo que tenga que hacer con el trabajo completado. Hay ejemplos en el enlace.

Como un caso general, nunca hubiera asumido que un recurso solo será modificado por el hilo. Puede que sepas para qué sirve, sin embargo, es posible que otra persona no lo haga, sin causar ningún tipo de dolor, ya que el hilo principal cree que el trabajo está hecho e intenta acceder a datos que no son correctos. Incluso podría eliminarlo mientras el subproceso de trabajo todavía lo esté utilizando y haciendo que la aplicación se cuelgue. Usar una condition ayudará a esto.

En cuanto a la documentación de la thread.timed_join también puede llamar a thread.timed_join en el hilo principal. timed_join esperará una cantidad específica para que el hilo ''se una'' (join significa que el hilo ha finalizado)


Tener el hilo establecer un indicador (o señalar un evento) antes de que salga es una condición de carrera. El hilo no ha regresado necesariamente al sistema operativo todavía y aún puede estar ejecutándose.

Por ejemplo, considere un programa que carga una biblioteca dinámica (pseudocódigo):

lib = loadLibrary("someLibrary"); fun = getFunction("someFunction"); fun(); unloadLibrary(lib);

Y supongamos que esta biblioteca usa tu hilo:

void someFunction() { volatile bool finished_flag = false; thrd = new boost::thread(boost::bind(&myclass::mymethod, this, &finished_flag); while(!finished_flag) { // ignore the polling loop, it''s besides the point sleep(); } delete thrd; } void myclass::mymethod() { // do stuff finished_flag = true; }

Cuando myclass::mymethod() establece finished_flag en true , myclass::mymethod() aún no ha regresado. Por lo menos, todavía tiene que ejecutar una instrucción de "retorno" de algún tipo (si no mucho más: destructores, gestión de manejador de excepciones, etc.). Si el subproceso que ejecuta myclass::mymethod() se myclass::mymethod() antes de ese punto, someFunction() volverá al programa que realiza la llamada y el programa que llama descargará la biblioteca. Cuando el subproceso que ejecuta myclass::mymethod() se programa para ejecutarse nuevamente, la dirección que contiene la instrucción "return" ya no es válida y el programa se bloquea.

La solución sería que someFunction() llame a thrd->join() antes de devolver. Esto garantizaría que el hilo haya regresado al SO y ya no se esté ejecutando.


No pretendo ser presuntivo, pero parece que el objetivo de la variable finished_flag es detener el hilo principal (en algún punto) hasta que se complete el hilo thrd .

La forma más fácil de hacerlo es usar boost :: thread :: join

// launch the thread... thrd = new boost::thread(boost::bind(&myclass::mymethod, this, &finished_flag); // ... do other things maybe ... // wait for the thread to complete thrd.join();


Si realmente desea entrar en los detalles de la comunicación entre subprocesos a través de la memoria compartida, incluso declarar que una variable es volátil no será suficiente, incluso si el compilador utiliza una semántica de acceso apropiada para asegurarse de que no obtendrá una versión obsoleta de los datos. después de verificar la bandera. La CPU puede emitir lecturas y grabaciones fuera de servicio siempre (x86 generalmente no lo hace, pero definitivamente PPC lo hace) y no hay nada en C ++ 9x que permita al compilador generar código para ordenar apropiadamente los accesos a la memoria.

La serie Effective Concurrency de Herb Sutter tiene una visión extremadamente profunda de cómo el mundo C ++ se cruza con el mundo multinúcleo / multiprocesador.