Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Creacin
Mantenimiento
Sincronizacin y
Destruccin
23
#include <pthread.h>
Ya que pthread es una librera POSIX, se podrn portar los programas hechos
con ella a cualquier sistema operativo POSIX que soporte threads. Por tanto, para crear
programas que hagan uso de la librera pthread.h necesitamos en primer lugar la librera
en s. Esta viene en la mayora de las distribuciones de LINUX y si no es as, se puede
bajar de la red.
Una vez que tenemos la librera instalada, deberemos compilar el programa y
ligarlo con dicha librera en base al compilador que se utilice. La librera de hilos
POSIX.1c debe ser la ltima librera especificada en la lnea de comandos del
compilador:
CC . . . lpthread
El espacio de direcciones
El ID del proceso
EL ID del proceso padre
El ID del proceso lder del grupo
Los identificadores de usuario
Los identificadores de grupo
El directorio de trabajo raz y actual
La mscara de creacin de archivos
La tabla de descriptores de archivos
El timer del proceso
Creacin y destruccin
Sincronizacin entre hilos
Posibilidad de disponer para cada thread memoria local propia
24
ID+Pila+Prioridad+Dir.Incio_Ejecucin
Thread
Hacemos referencia a los hilos POSIX mediante un ID de tipo:
pthread_t
25
TIPO DE DATO
pthread_attr_t
pthread_mutexattr_t
pthread_condattr_t
pthread_mutex_t
pthread_cond_t
pthread_t
pthread_once_t
pthread_key_t
DESCRIPCION
Atributo de hilo
Atributo de mutex
Atributo de variable de condicin
Mutex (bloqueo con exclusin mutua)
Variable de condicin
Hilo (Identificador de hilo o ID)
Ejecucin una sola vez
Clave sobre datos especficos de hilo
FUNCION
DESCRIPCION
Crea un nuevo hilo de
pthread_create
ejecucin
Compara
si
dos
pthread_equal
identificadores de hilo son
el mismo hilo
Finaliza el hilo que realiza
pthread_exit
la llamada
Sincroniza el hilo actual
con la finalizacin del hilo
pthread_join
especfico, devolviendo el
estado del hilo por el que
se espera
Devuelve el identificador
pthread_self
del hilo que realiza la
llamada
Convierte
el
hilo
pthread_detach
especificado
en
independiente
Obtiene la poltica de
planificacin
y
los
pthread_getschedparam
parmetros
del
hilo
especificado
Establece la poltica de
planificacin
y
los
pthread_setschedparam
parmetros
del
hilo
especificado
26
pthread_kill
CLASIFICACION
EXCLUSION
MUTUA
(Un mutex es
empleado para
proteger el acceso
compartido a los
recursos)
DESCRIPCION
Inicializa un mutex
pthread_mutex_init
con
los
atributos
especificados
Destruye el mutex
pthread_mutex_destroy
especificado
Adquiere el mutex
pthread_mutex_lock
indicado (bloquea el
mutex)
Intenta adquirir el
pthread_mutex_trylock
mutex indicado
Libera
el
mutex
previamente
pthread_mutex_unlock
adquirido (bloqueado)
que se especifica
Obtiene el valor de
prioridad
lmite
pthread_mutex_getprioceiling
(prioceiling) del mutex
especificado
Establece el valor de
prioridad
lmite
(prioceiling)
y
pthread_mutex_setprioceiling
devuelve el anterior
valor (old-ceiling) en
el mutex especificado
CLASIFICACION
VARIABLES DE
CONDICION
(Las variables de
condicin estan
asociadas con un mutex
y se emplean para
sincronizar los hilos)
FUNCION
FUNCION
DESCRIPCION
Inicializa una variable de
pthread_cond_init
condicin con los atributos
especificados
Destruye la variable de
pthread_cond_destroy
condicin especificada
Bloquea el hilo actual a la
pthread_cond_wait
espera de la variable de
condicin especificada.
Bloquea el hilo actual a la
espera de la variable de
condicin especificada, no
pthread_cond_timewait
ms
tiempo
del
especificado en forma
absoluta por abstime.
Desbloquea
un
hilo
actualmente bloqueado en
pthread_cond_signal
la variable de condicin
especificada
pthread_cond_broadcast Desbloquea todos los hilos
27
actualmente bloqueados en
la variable de condicin
especificada
CLASIFICACION
EJECUCION UNA
SOLA VEZ
(Mecanismo empleado
para inicializar datos u
objetos una sola vez
para todos los hilos)
FUNCION
DESCRIPCION
Esta funcin garantiza que una nueva
llamada a la rutina no ejecutar la funcin
nuevamente. Es decir, ejecuta una sola
vez la rutina de inicializacin init_routine
pthread_once
empleando para ello la variable de
control once_control declarada:
Pthread_once_t
once_control=
PTHREAD_ONCE_INIT
CLASIFICACION
DATOS ESPECIFICOS DE
HILO
(Si un hilo desea crear datos
que no sean globales a todos
los hilos pero si a sus
procedimientos, puede crear
datos especiales de este tipo)
CLASIFICACION
CANCELACION
(La cancelacin de es
gestionada como una
peticin de envo de una
seal interna especial
SIGCANCEL a un hilo. La
accin a tomar depende del
estado de cancelacin del
hilo receptor)
FUNCION
DESCRIPCION
Crea una clave para
datos especficos de hilo,
pthread_key_create que puede ser empleada
por todos los hilos del
proceso
Destruye una clave de
pthread_key_delete
datos especficos del hilo
Establece el valor para la
pthread_setspecific clave dada en el hilo que
realiza la llamada
Devuelve el ltimo valor
para la clave dada del
pthread_getspecific
hilo que realiza la
llamada
FUNCION
DESCRIPCION
Introduce (push) una
funcin en la cima de
la pila de cancelacin,
pthread_cleanup_push
que ser ejecutada
cuando se produzca la
cancelacin del hilo
Extrae
(pop)
una
funcin de la cima de
pthread_cleanup_pop
la pila de cancelacin y
opcionalmente
la
ejecuta
Establece el estado de
cancelacin y devuelve
pthread_setcancelstate el estado anterior para
el hilo que realiza la
llamada
Establece el tipo de
pthread_setcanceltype cancelacin y devuelve
28
pthread_cancel
pthread_testcancel
CLASIFICACION
ATRIBUTOS DE HILO
(Los atributos permiten
crear patrones de hilo para
crear hilos con las mismas
caractersticas )
ATRIBUTOS DE MUTEX
(Los atributos permiten
crear patrones de mutex
para crear mutex con las
mismas caractersticas)
ATRIBUTOS DE
VARIABLE DE
CONDICION
(Los atributos permiten
crear patrones de variables
de condicin para crear
variables de condicin con
las mismas caractersticas )
FUNCION
pthread_attr_init
pthread_attr_destroy
Inicializa un objeto
de atributos de
mutex
Destruye un objeto
pthread_mutexattr_destroy de atributos de
mutex
Inicializa un objeto
de atributos de
pthread_condattr_init
variable
de
condicin
Destruye un objeto
de atributos de
pthread_condattr_destroy
variable
de
condicin
pthread_mutexattr_init
CLASIFICACION
GESTION DE SEALES
(Cada hilo tiene su propia mscara
de seales. Los gestores de seales
son compartidos por todos los
hilos del proceso pues se instalan a
nivel proceso)
FUNCION
DESCRIPCION
Examina o modifica la
mscara de seales del
pthread_sigmask
hilo que realiza la
llamada
Enva
la
seal
pthread_kill
especificada
al
hilo
indicado
Acepta de forma sncrona
una seal (suspende el
sigwait
hilo hasta la llegada de la
seal indicada).
29
Donde:
*hilo: Es una variable de tipo pthread_t que contendr los datos del thread y que nos
servir para identificar el thread en concreto cuando nos interese hacer llamadas a la
librera para llevar a cabo una accin sobre l.
*atributo: Es un parmetro del tipo pthread_attr_t que se debe inicializar previamente
con los atributos que queramos que tenga el thread. Entre los atributos estn la
prioridad, el quantum, el algoritmo de planificacin a utilizar, etc. Lo normal es pasar
como parmetro de este argumento el valor NULL para que la librera le asigne al
thread los atributos por defecto.
*rutina: Es la direccin de la funcin que se quiere que ejecute el thread. La funcin
debe devolver un apuntador genrico (void *) como resultado y debe tener como nico
parmetro otro apuntador genrico. La ventaja de tener apuntadores genricos (void *)
es que se puede devolver cualquier cosa que se nos ocurra mediante los castings de tipos
necesarios. Si necesitamos pasar o devolver ms de un parmetro a la vez, se puede
crear una estructura y meter all dentro todo lo que necesitemos. Luego pasaremos o
devolveremos la direccin de sta estructura como nico parmetro.
*arg: Es una apuntador al parmetro que se le pasar a la funcin. Puede ser NULL si
no se le quiere pasar nada a la funcin.
La funcin devuelve un cero si todo ha ido bien, o un valor distinto de cero en
caso de que haya ocurrido algn error. Una vez que se ha llamado a la funcin
pthread_create(), se tienen entonces los hilos funcionando con dos opciones:
a) Esperar a que terminen los threads, en el caso de que sea de inters recoger algn
resultado, o bien
b) Simplemente decirle a la librera de pthreads que cuando termine la ejecucin de la
funcin del thread en cuestin elimine todos sus datos de sus tablas internas.
Para ello se disponen de dos funciones ms: pthread_join() y pthread_detach()
30
Sintaxis:
int pthread_join(pthread_t *hilo, void **thread_return);
Esta funcin indica a la librera que no queremos que nos guarde el resultado de
la ejecucin del thread indicado por el parmetro *hilo. Por defecto la librera guarda el
resultado de la ejecucin de todos los threads hasta que hacemos un pthread_join() para
recoger el resultado. As que si no nos interesa el resultado de los threads, tenemos que
indicarlo con esta funcin. Una vez que el hilo haya terminado, la librera eliminar los
datos del thread de sus tablas internas y se tendr ms espacio disponible para crear
otros hilos.
La funcin devuelve cero en caso de xito o un valor diferente de cero en caso
contrario.
Finalmente, para devolver valores cuando un thread finaliza, se utiliza la funcin
pthread_exit():
Sintaxis:
void pthread_exit(void *thread_return);
Esta funcin termina la ejecucin del thread que la llama. El valor del parmetro
*thread_return queda disponible para pthread_join() si sta tuvo xito. El parmetro
de sta funcin es un apuntador genrico a los datos que se quieren devolver como
resultado. Estos datos sern recogidos ms tarde cuando se haga un pthread_join() a
travs del identificador de nuestro hilo. La funcin no devuelve ningn valor.
PROGRAMA 1: El siguiente programa crear MAX_THREADS threads que
ejecutarn la funcin funcion_thr(). Esta funcin sacar un mensaje por pantalla del
tipo: Hola, soy el thread nmero y, donde y ser un nmero diferente para cada hilo.
Para pasar esos parmetros a la funcin, utilizaremos un struct de C donde se
introducir la cadena que debe imprimir cada hilo ms su identificador (la cadena la
podramos haber metido directamente dentro de la funcin, pero as veremos como se
pasa ms de un parmetro al hilo).
31
10
thr_param_t param[MAX_THREADS];
//tenemos que crear una tabla para los parametros porque los pasamos
//por referencia. Asi, si solo tuvieramos una variable para los
//parmetros al modificar esta modificariamos todas las que habiamos
//pasado anteriormente porque los threads no se quedan con el valor
//sino con la direccion
// Esta es la funcion que ejecutan los threads
void * funcion_thr(void *p)
{
thr_param_t *datos;
datos= (thr_param_t *)p;
printf("%s %d\n", datos->cadena, datos->id);
pthread_exit(&(datos->id)); //una vez terminamos, devolvemos el
//valor
}
int main(void)
{
int i, *res;
void * r;
printf("Creando threads...\n");
for (i=0; i<MAX_THREADS; i++)
{
param[i].cadena="Hola, soy el thread";
param[i].id= i;
pthread_create(&tabla_thr[i],NULL,funcion_thr,(void*)¶m[i]);
}
printf("Threads creados. Esperando que terminen...\n");
for (i=0; i<MAX_THREADS; i++)
{
pthread_join(tabla_thr[i],&r);
32
res=(int *)r;
printf("El thread %d devolvio el valor %d\n", i, *res);
}
printf("Todos los threads finalizados. Adios!\n");
system("PAUSE");
return 0;
}
Este primer programa ilustra el esquema bsico que siguen todas las aplicaciones
que lanzan threads para realizar un clculo y esperar su resultado:
33
34
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
void * imprimir_mensaje( void *puntero );
int main()
{
pthread_t hilo1, hilo2;
char *mensaje1 = "Hola";
char *mensaje2 = "Mundo";
pthread_create(&hilo1,NULL,imprimir_mensaje,(void*)
mensaje1);
pthread_create(&hilo2,NULL,imprimir_mensaje,(void*)
mensaje2);
printf("\n\n");
system("PAUSE");
exit(0);
return 1;
}
void * imprimir_mensaje( void *puntero )
{
char *mensaje;
mensaje = (char *) puntero;
printf("%s ", mensaje);
return puntero;
}
Aunque este programa parece correcto, posee errores que debemos considerar
como defectos considerables:
1. El defecto ms importante es que los hilos pueden ejecutarse concurrentemente. No
existe entonces garanta de que el primer hilo ejecute la funcin printf() antes que el
segundo hilo. Por tanto, podramos ver el mensaje Mundo Hola en vez de Hola
Mundo.
2. Por otro lado existe una llamada a exit( ) realizada por el hilo padre en la funcin
principal main( ). Si el hilo padre ejecuta la llamada a exit( ) antes de que alguno de
los hilos ejecute printf( ), la salida no se generar completamente. Esto es porque la
funcin exit( ) finaliza el proceso (libera la tarea) y termina todos los hilos.
Cualquier hilo padre o hijo que realice la llamada a exit( ) puede terminar con el
resto de los hilos del proceso. Los hilos que deseen finalizar explcitamente, deben
utilizar la funcin pthread_exit( ).
As nuestro programa Hola Mundo tiene 2 condiciones de ejecucin (race
conditions) o condiciones problemticas:
35
Este cdigo parece funcionar bien, sin embargo no es seguro. Nunca es seguro
confiar en los retrasos de tiempo. La condicin problemtica aqu es exactamente la
misma que se tiene con una aplicacin distribuida y un recurso compartido. El recurso
es la salida estndar y los elementos de la computacin distribuida son los tres hilos. El
hilo 1 debe usar la salida estndar antes que el hilo 2 y ambos deben realizar sus
acciones antes de que el hilo padre realice la llamada a exit( ).
Adems de nuestros intentos por sincronizar los hilos mediante retrasos, hemos
cometido otro error. La funcin sleep( ), al igual que la funcin exit( ) es relativa a
procesos. Cuando un hilo ejecuta sleep( ) el proceso entero duerme, es decir, todos los
hilos duermen cuando el proceso duerme. Nos encontramos por tanto en la misma
situacin que tenamos sin las llamadas a sleep() y encima el programa tarda 200
milisegundos ms en su ejecucin.
36
int main()
{
pthread_t hilo1, hilo2;
param_t mensaje1 = {"Hola", 0};
param_t mensaje2 = {"Mundo", 0};
pthread_create(&hilo1,NULL,imprimir_mensaje,(void*)&mensaje1);
mensaje2.hilo = hilo1;
pthread_create(&hilo2,NULL,imprimir_mensaje,(void*)&mensaje2);
pthread_join( hilo2, NULL );
system("PAUSE");
exit(0);
return 1;
}
37
38
ste cdigo que tiene a la variable i como global puede ser problemtico si se
ejecuta en paralelo y se dan ciertas condiciones.
Supongamos que el hilo 1 empieza a ejecutarse antes que el hilo 2 y que
casualmente se produce un cambio de contexto (el S.O. suspende la tarea actual y pasa a
ejecutar la siguiente) justo despus de la lne que dice if (i == valor_cualquiera).
Supondremos adems que la condicin se cumple por lo que la entrada en ese if
se producir. Pero justo en ese momento se realiza el cambio de contexto por el sistema
y pone a ejecutar el hilo 2, que se ejecuta el tiempo suficiente como para ejecutar la
lnea: i =*arg;
Al poco rato, el hilo 2 deja de ejecutarse volviendo a la ejecucin del hilo 1.
Qu valor tiene ahora i ? El que el hilo 1 esta suponiendo que tiene o el que le
a asignado el hilo 2 ?: i ha tomado el valor asignado por el hilo 2, con lo que el
resultado que devolver el hilo 1 despus de sus clculos ser invlido o inesperado.
Estos son los errores ms difciles de detectar, ya que puede que a veces vaya
todo a la perfeccin cuando se ejecuta el cdigo, pero puede ser que en otras ocasiones
dalga todo mal. A esto se le conoce como: Race Conditions (Condiciones de carrera)
porque segn como vaya la cosa puede funcionar o no.
39
la cola de espera del semforo. Los threads por tanto se excluyen mutuamente (mutex)
el uno al otro para entrar.
Forma de implementar las RC: Se pide el bloqueo del semforo antes de entrar, ste
es otorgado al primero que llega mientras que los dems se quedan bloqueado,
esperando a que el que entr primero libere el bloqueo o exclusin. Una vez que el que
entr sale de la regin crtica, ste debe notificarlo a la librera de los Pthreads para que
mire si hay algn otro thread esperando a entrar en la cola. Si es as, le da el bloqueo al
primero y deja que siga ejecutndose.
40
Esta funcin inicializa un mutex. Hay que llamarla antes de usar cualquiera de
las funciones que trabajan con mutex.
*mutex: es un apuntador a un parmetro del tipo pthread_mutex_t que es el tipo de
datos que utiliza la librera Pthreads para controlar los mutex.
*attr: Es un apuntador a una estructura del tipo pthread_mutexattr_t y sirve para definir
que tipo de mutex queremos: normal, recursivo o errorcheck. Si este valor es NULL
(recomendado), la librera le asignar un valor por defecto.
La funcin devuelve 0 (cero) si se pudo crear el mutex o -1 si hubo algn error.
Ejemplo 1. El siguiente segmento de cdigo inicializa el mutex my_lock con los
atributos por defecto. La variable my_lock debe ser accesible para todos los hilos que la
usan:
#include
#include
#include
#include
<stdio.h>
<pthread.h>
<string.h>
<errno.h>
pthread_mutex_t
my_lock;
if (! Pthread_mutex_init(&my_lock, NULL))
perror(No puede inicializarse my_lock);
my_lock= PTHREAD_MUTEX_INITIALIZER;
41
La function pide el bloqueo para entrar en una regin crtica (RC). Si se quiere
implementar una RC todos los hilos tendrn que pedir el bloqueo sobre el mismo
candado. Esta funcin devuelve 0 (cero) si no hubo error, o un valor diferente de cero si
lo hubo.
Al finalizar el bloqueo, se debe desbloquear el mutex mediante la funcin
pthread_mutex_unlock( ).
SINTAXIS:
int pthread_mutex_unlock(pthread_mutex_t *mutex);
42
43
Como puede observarse lo nico que hay que hacer es: inicializar el candado o
mutex, pedir el bloqueo antes de la RC y liberarlo despus de salir de la RC.
Ejemplo 5. muestra un fragmento de cdigo donde el mutex m esta asociado con la
variable global cabeza. Las funciones pthread_mutex_lock( ) y pthread_mutex_unlock(
) proporcionan exclusin mutua, lo que permite aadir sin problemas de interferencias,
la variable local nuevo_elemento a la lista enlazada cuya cabeza es cabeza.
typedef struct lista
{
char car;
lista_t *next;
} lista_t;
pthread_mutex_t m;
lista_t *cabeza;
void insertar_elemento(lista_t *nuevoElemento)
{
pthread_mutex_lock(&m)
nuevoElemento next = cabeza;
cabeza= nuevoElemento;
pthread_mutex_unlock(&m);
}
44
El valor bufout indica el nmero de ranura del siguiente elemento de datos que
se va a sacar y el valor bufin indica la siguiente ranura que se llenar. Si los hilos
productores y consumidores no actualizan bufout y bufin de una forma mutuamente
exclusiva, un productor prodra sobrescribir un elemento que no ha sido sacado o un
consumidor podra sacar un elemento que ya se us.
El cdigo siguiente muestra un programa que implementa un buffer circular
como un objeto compartido. El cdigo esta en un archivo aparte para que el programa
slo pueda acceder a buffer a travs de get_item (obtener elemento) y put_item (insertar
elemento).
#include <pthread.h>
#define BUFSIZE 8
static int buffer[BUFSIZE];
static int bufin=0;
static int bufout=0;
static pthread_mutex_t buffer_lock= PTHREAD_MUTEX_INITIALIZER;
/* Obtener el siguiente elemento del buffer y
*itemp */
void get_item(int *itemp)
{
pthread_mutex_lock(&buffer_lock);
*itemp=buffer[bufout];
bufout=(bufout+1) % BUFSIZE;
// printf("Tamano de bufout: %d\n",bufin);
pthread_mutex_unlock(&buffer_lock);
return;
}
colocarlo
bufin
en
45
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "buffer_circ.h"
#define SUMSIZE 100
int sum=0;
void put_item(int);
void get_item(int *);
void producer(void *arg1)
{
int i;
for(i=1;i<=SUMSIZE;i++)
{
printf("Se ejecuta PRODUCER: %d\n",i);
put_item(i*i);
}
}
void consumer(void *arg2)
{
int i, myitem;
for(i=1;i<=SUMSIZE;i++)
{
printf("Se ejecuta CONSUMER: %d\n",i);
get_item(&myitem);
sum+=myitem;
}
}
int main(void)
{
pthread_t prodtid;
pthread_t constid;
int i, total;
total=0;
for(i=1;i<=SUMSIZE;i++)
total+=i*i;
printf("La suma actual debe ser %d\n",total);
/* CREAR HILOS */
if(pthread_create(&constid,NULL,(void*(*)(void*))&consumer,NULL)
)
perror("No se pudo crear el hilo consumer...");
46
else
if(pthread_create(&prodtid,NULL,(void*(*)(void*))&producer,NULL)
)
perror("No se pudo crear el hilo producer...");
/* ESPERAR A QUE LOS HILOS TERMINEN */
pthread_join(prodtid,NULL);
pthread_join(constid,NULL);
printf("Los threads produjeron la suma: %d\n",sum);
system("PAUSE");
exit(0);
return 1;
}
47
Se ejecuta CONSUMER: 92
Se ejecuta CONSUMER: 93
Se ejecuta CONSUMER: 94
Se ejecuta CONSUMER: 95
Se ejecuta CONSUMER: 96
Se ejecuta CONSUMER: 97
Se ejecuta CONSUMER: 98
Se ejecuta CONSUMER: 99
Se ejecuta CONSUMER: 100
Los threads produjeron la suma: 315430
Presione una tecla para continuar . . .
<pthread.h>
<stdio.h>
<stdlib.h>
<string.h>
<errno.h>
"buffer_circ.h"
48
if(pthread_create(&constid,NULL,(void*(*)(void*))&producer,NULL)
)
perror("No se pudo crear el hilo consumer...");
else
if(pthread_create(&prodtid,NULL,(void*(*)(void*))&consumer,NULL)
)
perror("No se pudo crear el hilo producer...");
49
50
exacto de hilos que pueden ejecutarse de forma concurrente y del orden en que inician
su ejecucin.
Un programa multihilo debe funcionar correctamente, sea cual fuere el orden de
ejecucin y el nivel de paralelismo. Los elementos y ranuras del problema de
productores y consumidores deben sincronizarse de modo que el programa sea
independiente del orden de ejecucin de los hilos. Un mtodo tradicional de
sincronizacin es aquel que emplea semforos.
51
Adquiera el mutex
Pruebe el predicado
Si el predicado se cumple, realice el trabajo y libere el mutex
Si el predicado no se cumple, llame a cond_wait y pase al paso 2 cuando
retorne.
predicado es falso. Cuando otro hilo modifica variables que podran hacer que se
cumpliera el predicado, activa al hilo bloqueado ejecutando pthread_cond_signal( ).
int pthread_cond_signal(pthread_cond_t *cond);
A fin de garantizar que la prueba del predicado y la espera sean atmicas, el hilo
invocador debe obtener un mutex antes de probar el predicado. La implementacin
garantiza que si el hilo se bloquea en una variable de condicin, pthread_cond_wait( )
libera automticamente el mutex y se bloquear. Otro hilo no podr emitir una seal
antes de que este hilo se bloquee.
52
y el siguiente fragmento puede ser empleado para un hilo que aade un elemento a la
cabeza de la lista:
void insertar_elemento(lista_t *nuevoelemento)
{
pthread_mutex_lock(&m);
nuevoelemento next = cabeza;
cabeza = nuevoelemento;
pthread_cond_signal(&condNoVacio);
pthread_mutex_unlock(&m);
}
53
<pthread.h>
<stdio.h>
<stdlib.h>
<string.h>
<errno.h>
"buffer_circ.h"
54
for(i=1;i<=SUMSIZE;i++)
{
pthread_mutex_lock(&slot_lock); //Adquirir derecho a una
//ranura...
while (nslots<=0)
pthread_cond_wait(&slots,&slot_lock);
nslots--;
pthread_mutex_unlock(&slot_lock);
printf("Se ejecuta PRODUCER...%d\n",i);
put_item(i*i);
pthread_mutex_lock(&item_lock);
//renunciar derecho a un
//elemento...
nitems++;
pthread_cond_signal(&items);
pthread_mutex_unlock(&item_lock);
}
pthread_mutex_lock(&item_lock);
producer_done=1;
pthread_cond_broadcast(&items);
pthread_mutex_unlock(&item_lock);
}
void consumer(void *arg2)
{
int i=0, myitem;
for( ; ; )
{
pthread_mutex_lock(&item_lock); /* Adquirir derecho a un
elemento */
while((nitems<=0)&& !producer_done)
pthread_cond_wait(&items,&item_lock);
if((nitems<=0) && producer_done)
{
pthread_mutex_unlock(&item_lock);
break;
}
nitems--;
pthread_mutex_unlock(&item_lock);
i++;
printf("Se ejecuta CONSUMER...%d\n",i);
get_item(&myitem);
sum+=myitem;
pthread_mutex_lock(&slot_lock); /*renunciar derecho a una
ranura */
nslots++;
pthread_cond_signal(&slots);
pthread_mutex_unlock(&slot_lock);
}
}
55
int main(void)
{
pthread_t prodtid;
pthread_t constid;
int i, total;
total=0;
for(i=1;i<=SUMSIZE;i++)
total+=i*i;
printf("La suma actual debe ser %d\n",total);
/* CREAR HILOS */
pthread_create(&constid,NULL,(void*(*)(void*))&consumer,NULL);
pthread_create(&prodtid,NULL,(void*(*)(void*))&producer,NULL);
/* ESPERAR A QUE LOS HILOS TERMINEN */
pthread_join(prodtid,NULL);
pthread_join(constid,NULL);
printf("Los threads produjeron la suma: %d\n",sum);
system("PAUSE");
exit(0);
return 1;
}
56
57