Está en la página 1de 8

rea de Ingeniera Telemtica

Departamento de Ingeniera de Sistemas y Automtica


Escuela Superior de Ingenieros
Universidad de Sevilla
HILOS
1. OBJETIVO
El objetivo es estudiar los mecanismos para la creacin y destruccin de hilos (procesos
ligeros) de un mismo proceso, as como la sincronizacin entre stos mediante mutex y variables
condicionales.
2. DESCRIPCIN
os servicios para la utilizacin de proceso ligeros (hilos) se pueden agrupar de la
siguiente !orma"
#ervicios para la gestin de atributos de un proceso ligero.
$reacin e identi!icacin de procesos ligeros.
%erminacin de procesos ligeros.
#incronizacin entre procesos ligeros de un mismo proceso.
2.1 SERVICIOS PARA LA GESTIN DE ATRIBUTOS DE UN PROCESO LIGERO
$uando se crea un hilo, si no se le pasa un objeto del tipo atributo, se crea con los
atributos por de!ecto. #i se &uiere crear un hilo con otros valores para estos atributos (distintos a
los de por de!ecto), previamente se debe tener un objeto atributo (donde se almacenan los valores
de los di!erentes atributos), inicializarlo, darle los valores apropiados, y pas'rselo a la !uncin
&ue crea el hilo. os atributos se almacenan en un objeto atributo de tipo pthread_attr_t. (
continuacin se describen los principales servicios relacionados con los atributos de un proceso
ligero.
Creacin y de!r"ccin de a!ri#"!$%
)ara la creacin y el inicio de un objeto atributo (utilizado en la creacin de un proceso
ligero) se utiliza la siguiente !uncin"
int pthread_attr_init(pthread_attr_t *attr);
)ara la destruccin del objeto de tipo atributo se utiliza"
int pthread_attr_destroy(pthread_attr_t *attr);
E!a#&eci'ien!$ y $#!encin de& e!ad$ de !er'inacin%
El servicio para el establecimiento (set) del atributo correspondiente al estado de
terminacin es"
int pthread_attr_setdetachstate(pthread_attr_t *attr,
int detachstate);
El valor del argumento detachstate puede ser"
PTHREAD_CREATE_DETACHED: El proceso ligero &ue se cree con este estado de
terminacin se considerar' independiente y liberar' sus recursos cuando !inalice su
ejecucin.
PTHREAD_CREATE_JOINA!E: El proceso ligero &ue se cree con este estado de
terminacin se considerar' como no independiente y no liberar' sus recursos cuando
!inalice su ejecucin. En este caso, es necesario &ue otro proceso espere por su
!inalizacin utilizando pthread_"#in.
El servicio para la obtencin ($et) del atributo correspondiente al estado de terminacin
es el siguiente"
int pthread_attr_getdetachstate(pthread_attr_t *attr,
int *detachstate);
E!a#&eci'ien!$ y $#!encin de& !a'a($ de &a )i&a%
$ada hilo tiene una pila cuyo tama*o se puede establecer en el momento de la creacin,
d'ndole al atributo &ue se va a utilizar en la creacin el valor adecuado. Esto se hace mediante el
servicio"
int pthread_attr_setstacksize (pthread_attr_t *attr,
int stac%si&e);
El servicio para obtener el tama*o de la pila es el siguiente"
int pthread_attr_getstacksize (pthread_attr_t *attr,
int *stac%si&e);
2.2 CREACIN E IDENTI*ICACIN DE PROCESOS LIGEROS
)ara crear un proceso ligero &ue ejecuta una determinada !uncin se utiliza el siguiente
servicio"
int pthread_create(pthread_t *thread, pthread_attr_t *attr,
'#id *(*start_r#(tine) ('#id *), '#id *ar$);
El primer argumento debe ser la direccin de memoria de una variable (o memoria
reservada) donde esta !uncin almacenar' el identi!icador del hilo &ue se crea, y este argumento
es del tipo puntero a pthread_t. El segundo argumento especi!ica los atributos de ejecucin
asociados al nuevo proceso ligero. #i este argumento es N)!! se tomar'n los atributos por
de!ecto, &ue incluyen la creacin del proceso como no independiente (JOINA!E). El tercer
argumento indica el nombre de la !uncin a ejecutar cuando el proceso ligero comienza su
ejecucin. Esta !uncin re&uiere un solo par'metro &ue se especi!ica con el cuarto argumento,
ar$.
)ara obtener el identi!icador de un hilo se utiliza el servicio"
pthread_t pthread_self('#id);
2.+ TER,INACIN DE PROCESOS LIGEROS
os servicios relacionados con la terminacin de procesos ligeros son dos" para esperar
por la terminacin de un proceso ligero y para !inalizar la ejecucin de un proceso ligero.
)ara esperar por la terminacin de un proceso ligero se utiliza la !uncin"
int pthread_join(pthread thid, '#id *'a*(e);
Este servicio permite esperar a &ue termine un hilo. a !uncin suspende la ejecucin del
hilo llamante hasta &ue el hilo con identi!icador thid !inaliza su ejecucin. +evuelve en el
segundo argumento el valor devuelto por el hilo &ue termina (mediante pthread_e+it,
comentado a continuacin). ,nicamente se puede solicitar el servicio pthread_"#in sobre
hilos creados como no independientes.
)ara !inalizar la ejecucin de un hilo se utiliza"
'#id pthread_exit('#id *'a*(e);
El argumento es un puntero a una estructura &ue es devuelta al hilo &ue ha ejecutado la
correspondiente llamada a pthread-join.
( continuacin se presentan varios ejemplos &ue muestran la utilizacin de estos
servicios. )ara obtener el ejecutable, es necesario usar la opcin ,*pthread al enlazar el
programa"
$cc pr(e-a.c /# pr(e-a /*pthread
E-e')&$ 1" programa &ue crea dos procesos ligeros y espera su !inalizacin.
0inc*(de 1pthread.h2
0inc*(de 1stdi#.h2
'#id 3(nc('#id)
4

print3(5Thread 6d 7n5, pthread_se*3());
pthread_e+it(N)!!);
8
int 9ain('#id)
4
pthread_t th:, th;;
<* se crean d#s pr#ces#s *i$er#s c#n atri-(t#s p#r de3ect# *<
pthread_create(=th:, N)!!, 3(nc, N)!!);
pthread_create(=th;, N)!!, 3(nc, N)!!);
print3(5E* pr#ces# *i$er# principa* c#ntin(a e"ec(tand#7n5);
<* se espera s( ter9inaci>n *<
pthread_"#in(th:, N)!!);
pthread_"#in(th;, N)!!);
ret(rn(?);
8
prueba..c
Estudiar el ejemplo anterior. /#on necesarias las variables th: y th;0
E-e')&$ 2" programa &ue crea diez procesos ligeros independientes.
0inc*(de 1pthread.h2
0inc*(de 1stdi#.h2
0inc*(de 1(nistd.h2
0de3ine @AA_THREADB :?
'#id 3(nc('#id)
4
print3(5Thread 6d 7n5, pthread_se*3());
pthread_e+it(N)!!);
8
int 9ain('#id)
4
int ";
pthread_attr_t attr;
pthread_t thidC@AA_THREADBD;
<* Be inician *#s atri-(t#s E se 9arcan c#9# independientes *<
pthread_attr_init(=attr);
pthread_attr_setdetachstate(=attr, PTHREAD_CREATE_DETACHED);

3#r(" F ?; " 1 @AA_THREADB; " GG)
pthread_create(=thidC"D, =attr, 3(nc, N)!!);
pthread_attr_destr#E(=attr);
<* E* pr#ces# *i$er# principa* n# p(ede esperar *a 3ina*i&aci>n *<
<* de *#s pr#ces#s *i$er#s H(e ha cread# E se s(spende d(rante (n *<
<* ciert# tie9p# esperand# s( 3ina*i&aci>n *<
s*eep(I);
ret(rn (?);
8
prueba1.c
Estudiar el ejemplo anterior. /2u pasa si el hilo principal termina antes &ue los procesos
ligeros creados0
E-e')&$ +" programa &ue crea un proceso ligero independiente por cada n3mero &ue se da
por teclado hasta introducir 4.
0inc*(de 1pthread.h2
0inc*(de 1stdi#.h2
'#id i9pri9ir(int *n)
4
print3(5Thread 6d 6d 7n5, pthread_se*3(), *n);
pthread_e+it(N)!!);
8
int 9ain('#id)
4
pthread_attr_t attr;
pthread_t thid;
int n(9F:;

pthread_attr_init(=attr);
pthread_attr_setdetachstate(=attr, PTHREAD_CREATE_DETACHED);

Jhi*e(n(9)
4
print3(5Escri-ir n(9er# enter# :7n5);
scan3(56d5, =n(9); <* espera *<
pthread_create(=thid, =attr, i9pri9ir, =n(9);
8
pthread_attr_destr#E(=attr);
ret(rn ?;
8
prueba5.c
Estudiar el ejemplo anterior. /2u pasara si el hilo creado tardara en imprimir m's &ue el
usuario en dar un nuevo n3mero por teclado0
2.. SINCRONI/ACIN ENTRE PROCESOS LIGEROS
os mecanismos de sincronizacin &ue se utilizan con los procesos ligeros son los mutex
(sem'!oros binarios) y las variables condicionales. %ambin se pueden utilizar los sem'!oros
normales ya vistos anteriormente.
6na variable condicional o!rece un mecanismo para &ue los hilos esperen el
cumplimiento de predicados en los &ue intervengan variables compartidas. as variables
compartidas se deber'n proteger con un mutex. $ada vez &ue un hilo modi!ica una de estas
variables compartidas, debe se*alizar (utilizando pthread_c#nd_si$na*) mediante la
variable condicional &ue se ha realizado un cambio. Esta se*al activar' a un hilo en espera (&ue
se habra &uedado blo&ueado utilizando pthread_c#nd_Jait) &ue debe comprobar de nuevo
si ahora se cumple su predicado. a espera en la variable condicional conlleva la liberacin
autom'tica del mutex asociado para &ue otros hilos puedan modi!icar las variables compartidas.
$uando se activa un hilo en espera se vuelve a competir por el mutex.
)ara utilizar un mutex, un programa debe declarar una variable de tipo
pthread_9(te+_t e iniciarla antes de utilizarla. +e !orma an'loga, para utilizar en un
programa una variable condicional es necesario declarar una variable de tipo
pthread_c#nd_t e iniciarla antes de utilizarla. ( continuacin se exponen los servicios
utilizados para el manejo de los mutex y de las variables condicionales.
Iniciar "n '"!e0
int pthread_mutex_init(pthread_9(te+_t *9(te+,
pthread_9(te+attr_t *attr);
El segundo argumento son los atributos con los &ue se crea inicialmente el mutex. #i es
N)!! se consideran los atributos por de!ecto.
De!r"ir "n '"!e0
int pthread_mutex_destroy(pthread_9(te+_t *9(te+);
O)eracin #a-ar 1c$')e!ir )$r e& '"!e02
int pthread_mutex_lock(pthread_9(te+_t *9(te+);
O)eracin "#ir 1&i#erar e& '"!e02
int pthread_mutex_unlock(pthread_9(te+_t *9(te+);
Iniciar "na 3aria#&e c$ndici$na&
int pthread_cond_init(pthread_c#nd_t *c#nd,
pthread_c#ndattr_t *attr);
El segundo argumento son los atributos con los &ue se crea inicialmente la variable
condicional. #i es 76 se consideran los atributos por de!ecto.
De!r"ir "na 3aria#&e c$ndici$na&
int pthread_cond_destroy(pthread_c#nd_t *c#nd);
E)erar en "na 3aria#&e c$ndici$na&
int pthread_cond_wait(pthread_c#nd_t *c#nd,
pthread_9(te+_t *9(te+);
Esta !uncin suspende al proceso ligero hasta &ue otro proceso ejecute una operacin de
se*alizacin sobre la variable condicional pasada como primer argumento. +e !orma atmica se
libera el mutex pasado como segundo argumento. $uando el proceso se despierte volver' a
competir por el mutex.
Se(a&ar "na 3aria#&e c$ndici$na&
int pthread_cond_signal(pthread_c#nd_t *c#nd);
#e despierta a un proceso suspendido en la variable condicional pasada como argumento
(al despertarse tiene &ue competir por el mutex). 7o tiene e!ecto si no hay ning3n proceso ligero
esperando en la variable condicional.
E-e')&$ ." )roductor8consumidor usando mutex y variables condicin.
0inc*(de 1pthread.h2
0inc*(de 1stdi#.h2
0de3ine @AA_)KKER :?;L <* ta9aM# de* -(33er *<
0de3ine DATOB_A_PROD)CIR :????? <* dat#s a pr#d(cir *<
'#id Pr#d(ct#r('#id);
'#id C#ns(9id#r('#id);
pthread_9(te+_t 9(te+; <* 9(te+ para c#ntr#*ar e* acces# a* -(33er c#9partid#
*<
pthread_c#nd_t n#_**en#; <* esperar si n# estN **en# *<
pthread_c#nd_t n#_'aci#; <* esperar si n# estN 'acO# *<
int n_e*e9ent#sF?; <* nP9er# de e*e9ent#s en e* -(33er *<
int -(33erC@AA_)KKERD; <* -(33er c#9Pn *<
int 9ain(int ar$c, char *ar$'CD)4
pthread_t th:, th;;
pthread_9(te+_init(=9(te+, N)!!);
pthread_c#nd_init(=n#_**en#, N)!!);
pthread_c#nd_init(=n#_'aci#, N)!!);
pthread_create(=th:, N)!!, Pr#d(ct#r, N)!!);
pthread_create(=th;, N)!!, C#ns(9id#r, N)!!);
pthread_"#in(th:, N)!!);
pthread_"#in(th;, N)!!);
pthread_9(te+_destr#E(=9(te+);
pthread_c#nd_destr#E(=n#_**en#);
pthread_c#nd_destr#E(=n#_'aci#);
e+it(?);
8
<* c>di$# de* pr#d(ct#r *<
'#id Pr#d(ct#r('#id) 4
int dat#, i ,p#s F ?;
3#r(iF?; i1DATOB_A_PROD)CIR; iGG ) 4
dat# F i; <* pr#d(cir dat# *<
pthread_9(te+_*#c%(=9(te+); <* acceder a* -(33er *<
Jhi*e (n_e*e9ent#s FF @AA_)KKER) <* si -(33er **en# *<
pthread_c#nd_Jait(=n#_**en#, =9(te+); <* se -*#H(ea *<
-(33erCp#sD F i;
p#s F (p#s G :) 6 @AA_)KKER;
n_e*e9ent#s F n_e*e9ent#s G :;
i3 (n_e*e9ent#s FF :)
pthread_c#nd_si$na*(=n#_'aci#); <* -(33er n# 'acO# *<
pthread_9(te+_(n*#c%(=9(te+);
print3(5Pr#d(ce 6d 7n5, dat#); <* pr#d(ce dat# *<
8
pthread_e+it(?);
8
<* c>di$# de* c#ns(9id#r *<
'#id C#ns(9id#r('#id) 4
int dat#, i ,p#s F ?;
3#r(iF?; i1DATOB_A_PROD)CIR; iGG ) 4
pthread_9(te+_*#c%(=9(te+); <* acceder a* -(33er *<
Jhi*e (n_e*e9ent#s FF ?) <* si -(33er 'acO# *<
pthread_c#nd_Jait(=n#_'aci#, =9(te+); <* se -*#H(ea *<
dat# F -(33erCp#sD;
p#s F (p#s G :) 6 @AA_)KKER;
n_e*e9ent#s F n_e*e9ent#s / : ;
i3 (n_e*e9ent#s FF @AA_)KKER / :);
pthread_c#nd_si$na*(=n#_**en#); <* -(33er n# **en# *<
pthread_9(te+_(n*#c%(=9(te+);
print3(5C#ns(9e 6d 7n5, dat#); <* c#ns(9e dat# *<
8
pthread_e+it(?);
8
prueba9.c
Estudiar el ejemplo anterior.
6tilizar los mecanismos de sincronizacin entre hilos para &ue en la prueba 5 no haya
problemas con la variable num.
:ealizar un cliente para el servidor de !icheros sin estados creado en la pr'ctica
correspondiente a :)$;s &ue copie un !ichero en otro utilizando n hilos &ue de !orma
concurrente envan las peticiones al servidor. os argumentos de entrada son n, el !ichero origen
y el !ichero destino.

También podría gustarte