Mis funciones de hilo son:
#include"stdio.h" #include"sys/types.h" #include"pthread.h" #include"semaphore.h" sem_t sem; int running = 1; int ret; void *pf(void *arg) //producer function { int semval; while(running) { sleep(1); sem_post(&sem); sem_getvalue(&sem,&semval); printf("produce : %d\n",semval); } } void *cf(void *arg) /*consumer function*/ { int semval; while(running) { sleep(1); sem_wait(&sem); sem_getvalue(&sem,&semval); printf("consume : %d\n",semval); } }y la función principal es:
int main() { pthread_t pf, cf; ret = sem_init(&sem,0,16); pthread_create(&pf,NULL,(void *)pf,NULL); /*create producer*/ pthread_create(&cf,NULL,(void *)cf,NULL); /*create consumer*/ sleep(1); running = 0; pthread_join(pf,NULL); pthread_join(cf,NULL); sem_destroy(&sem); return 0; }Cuando ejecuto el archivo ejecutable, devuelve un error de segmentación. Creo que el programa puede acceder a una memoria no válida, ¡pero no sé qué parte de mi código está mal!
Ha nombrado las variables y funciones de su subproceso con el mismo nombre: pf y cf . Entonces las variables sombrean los nombres de las funciones. Nunca es una buena idea tener el mismo nombre para variables y funciones.
Cambio
pthread_create(&pf,NULL,(void *)pf,NULL); /*create producer*/ pthread_create(&cf,NULL,(void *)cf,NULL); /*create consumer*/para
pthread_create(&pf,NULL,producer,NULL); /*create producer*/ pthread_create(&cf,NULL,consumer,NULL); /*create consumer*/ y cambie el nombre de sus funciones a producer y consumer respectivamente. Tenga en cuenta que el lanzamiento también es incorrecto (y no es necesario, incluso si lo lanza correctamente), que he eliminado.
Está devolviendo cualquier valor de las funciones de subproceso. Las funciones de subproceso deben devolver void * . Entonces necesita llamar a pthread_exit(NULL); o devolver un puntero nulo.
Otro problema importante es que está accediendo a la variable running sin ninguna sincronización, lo que conduce a la condición de carrera . Este es un comportamiento indefinido . Dependiendo de la programación del subproceso, si el subproceso main establece la running en 0 antes de que los subprocesos se ejecuten, es posible que sus subprocesos no ejecuten el ciclo while en absoluto.
pthread_t pf, cf; ret = sem_init(&sem,0,16); pthread_create(&pf,NULL,(void *)pf,NULL); /*create producer*/ pthread_create(&cf,NULL,(void *)cf,NULL); /*create consumer*/ en realidad está pasando los descriptores de hilo a pthread_create() como rutina de inicio. Tienen los mismos nombres que las funciones a las que parece referirse aquí, pero las sombrean. También tenga en cuenta que void * es un puntero a datos, que es incompatible con un puntero de función -> no convertir a void * aquí.
El código correcto sería, por ejemplo, así:
pthread_t pt, ct; ret = sem_init(&sem,0,16); pthread_create(&pt,NULL,pf,NULL); /*create producer*/ pthread_create(&ct,NULL,cf,NULL); /*create consumer*/ Por cierto, sugerencia general: habilite las advertencias del compilador: gcc -Wall -Wextra le habría dicho qué está mal.
editar: siguiendo la discusión sobre la respuesta de Blue Moon : simplemente usar un int para cerrar sus hilos es realmente problemático. La carrera de datos que ocurre aquí no importa en la práctica la mayor parte del tiempo, porque normalmente, solo desea decirle a sus subprocesos que se detengan y no le importa cuándo sucede exactamente esto. Pero (y eso es un gran pero ): su compilador ve este código:
while(running) { [...] } donde la condición para while es el único acceso para running esta función. Sin saber acerca de la concurrencia, podría asumir legalmente que running , una vez leído, nunca cambia. Por lo tanto, leerlo una vez y usar este valor de lectura (por ejemplo, almacenado en un registro) para la condición de ciclo para siempre sería una optimización válida y definitivamente no es lo que desea.
Ah, y agregar un volatile a la running no es la solución, pero las explicaciones de esto tienden a ser largas, solo busque en Google.
Una posibilidad sería usar un semáforo para detener el hilo también. Por ejemplo, tengo esto en uno de mis proyectos subprocesos:
/* check whether daemon shutdown was requested */ if (!sem_trywait(&forceExit)) { /* pass on to next thread */ sem_post(&forceExit); rcout = -2; break; } El hilo principal solo hace un solo sem_post(&forceExit) para cerrar todos los demás hilos.