Está en la página 1de 10

Programacin en POSIX Threads (Pthreads)

Victor J. Sosa Sosa



1. Programacin en POSIX Threads (Pthreads)
1.1. Introduccin

La biblioteca de pthreads es una biblioteca que cumple los estndares POSIX y que
nos permite trabajar con distintos hilos de ejecucin (threads) al mismo tiempo.
La diferencia entre un thread y un proceso es que los procesos no comparten memoria
entre s, a no ser que se haya declarado explcitamente usando alguno de los
mecanismos de IPC (InterProcess Communication) de Unix, mientras que los threads
s que comparten totalmente la memoria entre ellos. Adems, para crear threads se
usan las funciones de la biblioteca pthread o de cualquier otra que soporte threads
mientras que para crear procesos usaremos la llamada al sistema fork(), que se
encuentra en todos los sistemas unix.
Ya que pthreads es una biblioteca POSIX, se podrn portar los programas hechos con
ella a cualquier sistema operativo POSIX que soporte threads. Ejemplos de ello son
IRIX, los unix'es de BSD, Digital Unix OSF/1, etc.
1.2. 1.2. Como compilar un programa con pthreads
Para crear programas que hagan uso de la biblioteca pthreads necesitamos, en primer
lugar, la biblioteca en s. sta viene en la mayora de distribuciones linux, y
seguramente se instale al mismo tiempo que los paquetes incluidos para el desarrollo
de aplicaciones (es decir, cuando instalamos la libc o algn paquete tipo libc-devel)
Si no es as, o usas un sistema que no sea linux, la biblioteca no debera ser muy
difcil de encontrar en la red, porque es bastante conocida y se suele usar bastante.
Una vez tenemos la biblioteca instalada, deberemos compilar el programa y linkarlo
con la biblioteca dependiendo del compilador que estemos usando.
La forma ms usual de hacer esto es, si estamos usando como compilador GNU gcc
con el comando:
gcc pr ogr ama_con_pt hr eads. c - o pr ogr ama_con_pt hr eads - l pt hr ead
Si por el contrario no estamos usando el compilador de GNU, lo mejor ser que
miremos la pgina man del compilador de C instalado en el sistema. Por ejemplo, en el
caso del compilador de Digital para OSF/1, ste tiene un parmetro especial para
compilar con pthreads:
cc pr ogr ama_con_pt hr eads. c - o pr ogr ama_con_pt hr eads - pt hr ead
Como vers la sintaxis no es muy diferente pero el compilador de Digital no aceptar
la de gcc y viceversa.
1.3. 1.3. Creacin y manipulacin de threads
Para crear un thread nos valdremos de la funcin pt hr ead_cr eat e de la biblioteca y
de la estructura de datos pthread_t que identifica cada thread diferencindolo de los
dems y que contiene todos sus datos.
El prototipo de la funcin es el siguiente:
int pt hr ead_cr eat e( pt hr ead_t * t hr ead, pt hr ead_at t r _t *at t r ,
voi d * ( *st ar t _r out i ne) ( voi d *) , voi d *ar g)

thread: Es una variable del 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 biblioteca para llevar a cabo alguna accin sobre l.
attr: Es un parmetro del tipo pthread_attr_t y que se debe inicializar
previamente con los atributos que queramos que tenga el thread. Entre los
atributos hay la prioridad, el quantum, el algoritmo de planificacin que
queramos usar, etc. Si pasamos como parmetro aqu NULL, la biblioteca le
asignar al thread unos atributos por defecto (RECOMENDADO).
start_routine: Aqu pondremos la direccin de la funcin que queremos que
ejecute el thread. La funcin debe devolver un puntero genrico (void *) como
resultado, y debe tener como nico parmetro otro puntero genrico.
La ventaja de que estos dos punteros sean genricos es que podremos
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 esta estructura como nico parmetro. (ver
cdigo de ejemplo)
arg: Es un puntero al parmetro que se le pasar a la funcin. Puede ser NULL
si no queremos pasarle nada a la funcin.
En caso de que todo haya ido bien, la funcin devuelve un 0 o un valor distinto
de 0 en caso de que hubo algn error.

Una vez hemos llamado a esta funcin, ya tenemos a nuestro(s) thread(s)
funcionando, pero ahora tenemos dos opciones: esperar a que terminen los threads,
en el caso de que nos interese recoger algn resultado, o simplemente decirle a la
biblioteca de pthreads que cuando termine la ejecucin de la funcin del thread elimine
todos sus datos de sus tablas internas.
Para ello, disponemos de dos funciones ms de la biblioteca: pt hr ead_j oi n y
pt hr ead_det ach.

i nt pt hr ead_j oi n( pt hr ead_t t h, voi d **t hr ead_r et ur n)

Esta funcin suspende el thread llamante hasta que no termine su ejecucin el
thread indicado por th. Adems, una vez ste ltimo termina, pone en
thread_return el resultado devuelto por el thread que se estaba ejecutando.
th: Es el identificador del thread que queremos esperar, y es el mismo que
obtuvimos al crearlo con pthread_create.
thread_return: Es un puntero a puntero que apunta (valga la redundancia) al
resultado devuelto por el thread que estamos esperando cuando termin su
ejecucin. Si este parmetro es NULL, le estamos indicando a la biblioteca que
no nos importa el resultado.
Devuelve 0 en caso de todo correcto, o valor diferente de 0 si hubo algn error.

i nt pt hr ead_det ach( pt hr ead_t t h)
Esta funcin le indica a la biblioteca que no queremos que nos guarde el
resultado de la ejecucin del thread indicado por th. Por defecto la biblioteca
guarda el resultado de ejecucin de todos los threads hasta que nosotros
hacemos un pthread_join para recoger el resultado.
Es por eso que si no nos interesa el resultado de los threads tenemos que
indicarlo con esta funcin. As una vez que el thread haya terminado la
biblioteca eliminar los datos del thread de sus tablas internas y tendremos
ms espacio disponible para crear otros threads (IMPORTANTE)
th: Es el identificador del thread
Devuelve 0 en caso de que todo haya ido bien o diferente de 0 si hubo error.

Hasta ahora hemos estado hablando de devolver valores cuando un thread finaliza,
pero an no hemos dicho como se hace. Pues bien, para ello tenemos la funcin
pt hr ead_exi t

voi d pt hr ead_exi t ( voi d *r et val )
Esta funcin termina la ejecucin del thread que la llama.
retval: Es un puntero genrico a los datos que queremos devolver como
resultado. Estos datos sern recogidos ms tarde cuando alguien haga un
pthread_join con nuestro identificador de thread.
No devuelve ningn valor.

Con todo lo que hemos visto hasta ahora ya estamos preparados para hacer nuestro
primer programa con pthreads. El programa de ejemplo crear MAX_THREADS
threads que ejecutarn la funcin funcion_thr.
Esta funcin sacar un mensaje por pantalla del tipo "hola, soy el thread nmero x",
donde x ser un nmero diferente para cada thread.
Para pasar esos parmetros a la funcin usaremos un struct del C, donde meteremos
la cadena que debe imprimir cada thread 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 thread)
Una vez termina su ejecucin, el thread devolver como resultado su identificador
(codificado en un entero), que ser imprimido por pantalla por el thread padre que
esperar que todos los threads terminen.

/ *** <CORTAR AQUI > ***/
/ *** Ar chi vo ej 1. c *****/
/ * Cr eamos MAX_THREAD t hr eads que sacan por pant al l a una cadena y su
i dent i f i cador
Una vez t er mi nan su ej ecuci n devuel ven como r esul t ado su
i dent i f i cador */
#i ncl ude <pt hr ead. h>
#i ncl ude <st di o. h>
#i ncl ude <st dl i b. h>
#i ncl ude <st r i ng. h>
#def i ne MAX_THREADS 10
/ / t abl a con l os i dent i f i cador es de l os t hr eads
pt hr ead_t t abl a_t hr [ MAX_THREADS] ;
/ / t i po de dat os y t abl a con l os par amet r os
t ypedef st r uct {
i nt i d;
char *cadena;
} t hr _par am_t ;
t hr _par am_t par am[ MAX_THREADS] ;
/ / t enemos que cr ear una t abl a par a l os par met r os por que l os pasamos
por
/ / r ef er enci a. As , si sol o t uvi r amos una var i abl e par a l os
par met r os
/ / al modi f i car est a modi f i car amos t odas l as que hab amos pasado
ant er i or ment e
/ / por que l os t hr eads no se quedan con el val or si no con l a di r ecci n
voi d *f unci on_t hr ( t hr _par am_t *p)
{
/ / Est a es l a f unci on que ej ecut an l os t hr eads
/ / como ver as, no t i ene mucho secr et o. . .
pr i nt f ( " %s %d\ n" , p- >cadena, p- >i d) ;
/ / una vez t er mi namos, devol vemos el val or
pt hr ead_exi t ( &( p- >i d) ) ;
}
i nt mai n( voi d)
{
i nt i , *r es;
/ / cr eamos l os t hr eads
pr i nt f ( " Cr eando t hr eads. . . \ n" ) ;
f or ( i =0; i <MAX_THREADS; i ++) {
par am[ i ] . cadena = st r dup( " Hol a, soy el t hr ead" ) ;
par am[ i ] . i d = i ;
pt hr ead_cr eat e( &t abl a_t hr [ i ] , NULL, ( voi d *) &f unci on_t hr ,
( voi d *) &par am[ i ] ) ;
}
/ / esper amos que t er mi nen l os t hr eads
pr i nt f ( " Thr eads cr eados. Esper ando que t er mi nen. . . \ n" ) ;
f or ( i =0; i <MAX_THREADS; i ++) {
pt hr ead_j oi n( t abl a_t hr [ i ] , ( voi d *) &r es) ;
pr i nt f ( " El t hr ead %d devol vi o el val or %d\ n" , i , *r es) ;
}
/ / sacamos el mensaj i t o y sal i mos del pr ogr ama
pr i nt f ( " Todos l os t hr eads f i nal i zados. Adi os! \ n" ) ;
r et ur n 0;
}
/ *** <CORTAR AQUI > ***/

Para compilar (bajo Linux y gcc): gcc ej 1. c - o ej 1 - l pt hr ead

El ejemplo en s es MUY tonto, pero es el esquema bsico que siguen todas las
aplicaciones que lanzan threads para realizar un clculo y esperan su resultado:
1. Crear el/los thread(s)
2. Esperar que terminen
3. Recoger y procesar el/los resultado(s)
Esto es un ejemplo de lo que se llama paralelismo estructurado.
Un ejemplo de un programa que use la funcin pt hr ead_det ach podra ser el de un
servidor (de cualquier cosa: de correo, de http, de ftp, etc) que cree un hilo para cada
peticin que reciba. Como que no nos interesa el resultado de la ejecucin, una vez
hayamos creamos el thread llamaremos la funcion pt hr ead_det ach.
Esto es lo que se conoce por paralelismo no estructurado. Es decir, nuestros
programas no siguen una estructura concreta sino que se van ramificando segn
nuestras necesidades.
1.4. Otras funciones tiles de la biblioteca pthreads
Hasta ahora hemos visto las funciones ms bsicas para tratar con pthreads, pero an
queda alguna otra funcin til:
pt hr ead_t pt hr ead_sel f ( voi d)
Esta funcin devuelve al thread que la llama su informacin, en forma de
variable del tipo pthread_t.
Es til si el propio thread que se est ejecutando quiere cambiar sus atributos, hacerse
l mismo un pt hr ead_det ach, etc.
Devuelve el identificador del thread. Ejemplo:

#i ncl ude <pt hr ead. h>
. . .
voi d *f unci on_t hr eads( voi d *par am)
{
pt hr ead_t yo_mi smo;
. . .
/ * nosot r os mi smos nos hacemos el det ach */
yo_mi smo = pt hr ead_sel f ( ) ;
pt hr ead_det ach( yo_mi smo) ;
. . .
}
i nt mai n( voi d)
{
. . .
}
i nt pt hr ead_ki l l ( pt hr ead_t t hr ead, i nt si gno)

Enva un signal especificada al thread especificada. Un signal til de enviar
puede ser el SIGKILL, o alguno de los definidos por el usuario, SIGUSR1 y
SIGUSR2.
Aunque pueda parecer til a primera vista, la nica utilidad que tiene es matar
un thread desde el proceso padre. Si se quiere usar con fines de sincronizacin
hay formas mejores de hacerlo tratndose de threads: mediante semforos y
variables de condicin (enseguida lo veremos)
thread: identifica el thread al cual le queremos enviar el signal.
signo: nmero de la seal que queremos enviar al thread. Podemos usar las
constantes definidas en /usr/include/signal.h
Devuelve 0 si no hubo error, o diferente de 0 si lo hubo.

Hasta aqu la primera parte del tutorial de programacin en Pthreads. Aqu hemos
visto las funciones bsicas que nos ofrece la biblioteca para la creacin, manipulacin
y eliminacin de threads, pero an nos quedan algunas cosas por ver.
2. 2. Problemas de concurrencia con Pthreads
2.1. 2.1. Introduccin
Cuando decidimos trabajar con programas concurrentes uno de los mayores
problemas con los que nos podremos encontrar, y que es inherente a la concurrencia,
es el acceso a variables y/o estructuras compartidas o globales
Esto se entender mejor con un ejemplo:


Hi l o 1
voi d *f unci on_hi l o_1( voi d *ar g)
{
i nt r esul t ado;
. . .
i f ( i == val or _cual qui er a) {
. . .
r esul t ado = i *
( i nt ) *ar g;
. . .
}
pt hr ead_exi t ( &r esul t ado) ;
}

Hi l o 2
voi d *f unci on_hi l o_2( voi d *ar g)
{
i nt ot r o_r esul t ado;
. . .
i f ( f unci on_sobr e_ar g( *ar g) ==
0) {
. . .
i = *ar g;
. . .
}
pt hr ead_exi t ( &ot r o_r esul t ado) ;
}



Este cdigo, que tiene la variable 'i' como global, aparentemente es inofensivo, pero
nos puede traer muchos problemas si se ejecuta en paralelo y se dan ciertas
condiciones.
Supongamos que el hilo 1 se empieza a ejecutar antes que el hilo 2, y que
casualmente se produce un cambio de contexto (el sistema operativo suspende la
tarea actual y pasa a ejecutar la siguiente) justo despus de la lnea que dice if
(i==valor_cualquiera). La entrada en ese if se producir si se cumple la condicin, que
suponemos que s.
Pero justo en ese momento el sistema hace un cambio de contexto y pone a ejecutar
al hilo2, que se ejecuta el tiempo suficiente como para ejecutar la lnea i =*arg. Al
poco rato hilo 2 deja de ejecutarse y vuelve a ejecutarse el hilo 1, pero, qu valor tiene
ahora i? El que el hilo 1 est "suponiendo" que tiene (o sea, el mismo que comprob al
entrar en el if) o el que le ha asignado el hilo 2? La respuesta es fcil... ;-) i ha tomado
el valor que le asign hilo 2, con lo que el resultado que devolver el hilo 1 despus de
sus clculos ser totalmente invlido e inesperado.
Claro que todo esto puede que no pasar si el sistema tuviera muy pocos procesos en
ese momento (con lo cual cada proceso se ejecutara por ms rato) y si el cdigo del
hilo 1 fuera lo suficientemente corto como para no sufrir ningn cambio de contexto en
medio de su ejecucin... Pero NUNCA deberemos hacer suposiciones de stas,
porque no sabremos dnde se van a ejecutar nuestros programas y siempre ms vale
prevenir.
El problema que tienen estos bugs es que son los ms difciles de detectar en el caso
que no nos fijramos en que podra pasar una cosa de estas el da que escribimos el
cdigo. Puede que a veces vaya todo a la perfeccin y que otras salga todo mal... A
esto se le conoce por Race Conditions (o en cristiano, Condiciones de Carrera) porque
segn como vaya la cosa puede funcionar o no.
2.2. 2.2. Mecanismos de Pthreads para prevenir esto
La biblioteca de Pthreads nos ofrece unos mecanismos bsicos pero muy tiles para
definir esto. Estos mecanismos son los llamados semforos binarios, y se usan para
implementar las llamadas regiones crticas (RC) o zonas de exclusin mtua (ZE).
Y qu es una RC? Pues una parte de nuestro cdigo que es susceptible de verse
afectada por cosas como la del ejemplo. Como regla general, SIEMPRE que haya
variables o estructuras globales que vayan a ser accedidas por ms de un thread a la
vez, el acceso a stas deber ser considerado una regin crtica, y protegido con los
medios que vamos a explicar a continuacin. Incluso si estamos seguros que solo un
hilo va a acceder a una determinada estructura, no sera mala idea meter ese cdigo
en una RC porque tal vez en un futuro ampliemos nuestro cdigo y no recordemos que
tenamos esos accesos por ah escondidos, con el consiguiente riesgo de bugs que
ello conlleva.
Lo que Pthreads nos ofrece son los semforos binarios, semforos mutex o
simplemente mutexs, como cada uno quiera llamarlo ;-) Un semforo binario es una
estructura de datos que acta como un semforo porque puede tener dos estados: o
abierto o cerrado. Cuando el semforo est abierto, al primer thread que pide un
bloqueo se le asigna ese bloqueo y no se deja pasar a nadie ms por el semforo.
Mientras que si el semforo est cerrado, porque algn thread ya tiene el bloqueo, el
thread que lo pidi parar su ejecucin hasta que no sea liberado el susodicho
bloqueo.
Solo puede haber un solo thread poseyendo el bloqueo del semforo, mientras que
puede haber ms de un thread esperando para entrar en la RC, encolados en la cola
de espera del semforo. Es decir, los threads se excluyen mtuamente (de ah lo de
mutex para el nombre) el uno al otro para entrar.
Pues con una cosa tan sencilla en concepto se implementan las RC: se pide el
bloqueo del semforo antes de entrar, ste es otorgado al primero que llega, mientras
que los dems se quedan bloqueados esperando a que el que entr primero libere el
bloqueo o exclusin. Una vez el que entr sale de la RC, ste debe notificarlo a la
biblioteca de pthreads para que mire si haba algn otro thread esperando para entrar
en la cola. Si lo haba, le da el bloqueo al primero y deja que siga ejecutndose.
Las funciones que ofrece Pthreads para llevar esto a cabo son:

i nt pt hr ead_mut ex_i ni t ( pt hr ead_mut ex_t *mut ex,
const pt hr ead_mut exat t r _t *at t r )

Esta funcin inicializa un mutex. Hay que llamarla antes de usar cualquiera de
las funciones que trabajan con mutex.
mutex: Es un puntero a un parmetro del tipo pt hr ead_mut ex_t , que es el
tipo de datos que usa la biblioteca Pthreads para controlar los mutex.
attr: Es un puntero a una estructura del tipo pt hr ead_mut exat t r _t , y sirve
para definir qu tipo de mutex queremos: normal, recursivo o errorcheck (esto
se ver ms adelante)
Si este valor es NULL (recomendado), la biblioteca le asignar un valor por
defecto.
La funcin devuelve 0 si se pudo crear el mutex o -1 si hubo algn error.

i nt pt hr ead_mut ex_l ock( pt hr ead_mut ex_t *mut ex)
Esta funcin pide el bloqueo para entrar en una RC. Si queremos implementar
una RC, todos los thread tendrn que pedir el bloqueo sobre el mismo
semforo.
mutex: Es un puntero al mutex sobre el cual queremos pedir el bloqueo o sobre
el que nos bloquearemos en caso de que ya haya alguien dentro de la RC.
Como resultado, devuelve 0 si no hubo error, o diferente de 0 si lo hubo.

i nt pt hr ead_mut ex_unl ock( pt hr ead_mut ex_t *mut ex)
Esta es la funcin contraria a la anterior. Libera el bloqueo que tuviramos
sobre un semforo.
mutex: Es el semforo donde tenemos el bloqueo y queremos liberarlo.
Retorna 0 como resultado si no hubo error o diferente de 0 si lo hubo.

i nt pt hr ead_mut ex_dest r oy( pt hr ead_mut ex_t *mut ex)
Le dice a la biblioteca que el mutex que le estamos indicando no lo vamos a
usar ms, y que puede liberar toda la memoria ocupada en sus estructuras
internas por ese mutex.
mutex: El mutex que queremos destruir.
La funcin, como siempre, devuelve 0 si no hubo error, o distinto de 0 si lo
hubo.

Estas son las funciones ms bsicas. Ahora, reescribiremos el pseudocdigo del
ejemplo anterior con lo que hemos visto hasta ahora.

Var i abl es gl obal es:

pt hr ead_mut ex_t mut ex_acceso;
i nt i ;

Hi l o 1 ( Ver si n cor r ect a)
voi d *f unci on_hi l o_1( voi d *ar g)
{
i nt r esul t ado;
. . .

pt hr ead_mut ex_l ock( &mut ex_acceso) ;
i f ( i == val or _cual qui er a) {
. . . <
r esul t ado = i * ( i nt ) *ar g;
. . . <
}

Hi l o 2 ( Ver si n cor r ect a)
voi d *f unci on_hi l o_2( voi d *ar g)
{
i nt ot r o_r esul t ado;
. . .
i f ( f unci on_sobr e_ar g( *ar g) == 0)
{
. . .

pt hr ead_mut ex_l ock( &mut ex_acceso) ;
i = *ar g;
pt hr ead_mut ex_unl ock( &mut ex_acceso) ;
. . .
pt hr ead_mut ex_unl ock( &mut ex_acceso) ;
pt hr ead_exi t ( &r esul t ado) ;
}

}
pt hr ead_exi t ( &ot r o_r esul t ado) ;
}

i nt mai n( voi d)
{
. . .
pt hr ead_mut ex_i ni t ( &mut ex_acceso, NULL) ;
. . .
}


En color azul han sido aadidas las lneas que antes no estaban.
Como se puede ver lo nico que hay que hacer es inicializar el semforo, pedir el
bloqueo antes de las RC y liberarlo despus de salir de la RC, aunque a veces es
cuestin tambin de tener un poco de vista.
Contra ms pequeas hagamos las RC, ms concurrentes sern nuestros programas,
porque tendrn que esperar menos tiempo en el caso de que haya bloqueos.
2.3. 2.3. Problemas... Ms problemas?
Aunque esto realmente soluciona el problema de los accesos concurrentes, tambin
nos puede traer ms problemas.
Y los problemas aqu tambin tienen nombre: los Deadlocks (o Abrazos Mortales) Los
Deadlocks se producen cuando un hilo se bloquea esperando un recurso que tiene
bloqueado otro hilo que est esperando un recurso. Si el recurso para el segundo
thread no llega nunca, no se desbloquear nunca, con lo cual tampoco se
desbloquear nunca el primer thread.
Resultado: nuestro fantstico programa bloqueado.
Solucin? Pues aunque la biblioteca de Pthreads nos de algn mecanismo para
intentar prevenir que esto se produzca, no hay ningn mecanismo fiable al 100% para
prevenirlos.
El modelo ms sencillo de Deadlock es el circular:

Hi l o 1
voi d *f unci on_hi l o_1( voi d *ar g)
{
. . .
pt hr ead_mut ex_l ock( &mut ex_1) ;
. . .

pt hr ead_mut ex_unl ock( &mut ex_2) ;
. . .
}

Hi l o 2
voi d *f unci on_hi l o_2( voi d *ar g)
{
. . .
pt hr ead_mut ex_l ock( &mut ex_2) ;
. . .

pt hr ead_mut ex_unl ock( &mut ex_1) ;
. . .
}

Parece un poco raro, pero puede llegarse a producir.
Mecanismos que ofrece la biblioteca Pthreads:

1. Semforos recursivos
Estos semforos solo aceptarn una sola peticin de bloqueo por el mismo
thread. Con los semforos normales, si el mismo thread hace 10 llamadas a
pt hr ead_mut ex_l ock sobre el mismo semforo, luego tendr que hacer 10
llamadas a pt hr ead_mut ex_unl ock, es decir, tantas como haya hecho a
pt hr ead_mut ex_l ock.
En cambio, los del tipo recursivo solo aceptarn una sola llamada a
pt hr ead_mut ex_l ock. Las siguientes llamadas sern ignoradas, con lo que
ya eliminamos un tipo de deadlock.
Para poder crear un semforo recursivo, tendremos que decrselo a
pt hr ead_mut ex_i ni t , indicndole como atributo el resultado de una llamada
a pt hr ead_mut exat t r _set t ype. El procedimiento es:
Definir una variable del tipo pt hr ead_mut exat t r _t :
pt hr ead_mut exat t r _t mut ex_at t r ;
Inicializarla con la llamada a pht r ead_mut exat t r _i ni t :
pt hr ead_mut exat t r _i ni t ( &mut ex_at t r ) ;
Indicarle el tipo explcitamente mediante pt hr ead_mut exat t r _set t ype:
pt hr ead_mut exat t r _set t ype( &mut ex_at t r , t i po) ;
Donde tipo puede ser PTHREAD_MUTEX_NORMAL, PTHREAD_MUTEX_DEFAULT
(el que se usa por defecto), PTHREAD_MUTEX_RECURSI VE o
PTHREAD_MUTEX_ERRORCHECK.

2. Probar antes de entrar
Si creemos que la siguiente llamada a pt hr ead_mut ex_l ock va a ser
bloqueante y que puede provocar un deadlock, la biblioteca de Pthreads nos
ofrece una funcin ms para comprobar si eso es cierto:
pt hr ead_mut ex_t r yl ock.
i nt pt hr ead_mut ex_t r yl ock( pt hr ead_mut ex_t *mut ex) ;
mutex: Es el mutex sobre el cual queremos realizar la prueba de bloqueo.
La funcin devuelve EBUSY si el thread llamante se bloquear o 0 en caso
contrario. Si no se produce el bloqueo, la funcin acta igual que
phtread_mutex_lock, adquiriendo el bloqueo sobre el semforo.

3. Funciones avanzadas
Otras funciones de uso avanzado con pthreads son las siguientes:

int pt hr ead_at t r _i ni t ( pt hr ead_at t r _t *at t r ) ;

i nt pt hr ead_at t r _dest r oy( pt hr ead_at t r _t *at t r ) ;

i nt pt hr ead_at t r _set det achst at e( pt hr ead_at t r _t *at t r , i nt
det achst at e) ;

i nt pt hr ead_at t r _get det achst at e( const pt hr ead_at t r _t *at t r , i nt
*det achst at e) ;

i nt pt hr ead_at t r _set schedpol i cy( pt hr ead_at t r _t *at t r , i nt
pol i cy) ;

i nt pt hr ead_at t r _get schedpol i cy( const pt hr ead_at t r _t *at t r , i nt
*pol i cy) ;

i nt pt hr ead_at t r _set schedpar am( pt hr ead_at t r _t *at t r , const
st r uct sched_par am*par am) ;

i nt pt hr ead_at t r _get schedpar am( const pt hr ead_at t r _t *at t r ,
st r uct sched_par am*par am) ;

Su utilizacin va ms all de los objetivos del curso y su estudio se deja al alumno

También podría gustarte