Hilos de ejecucin
Concepto
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
Hilos de ejecucin
Procesos multihilo
VARIABLES
GLOBALES
(accesibles por
todos los hilos)
Modo
usuario
Modo
ncleo
HILO PRINCIPAL
HILOS
SECUNDARIOS (con
sus propias variables
locales y parmetros)
HILO A NIVEL
DEL NCLEO
(planificable)
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
Modo
usuario
Modo
ncleo
Hilos de ejecucin
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
Esto significa que son hermanos, a diferencia de los proceso cuya relacin es
padre-hijo
Adems, cada uno tiene una copia privada de sus parmetros iniciales y de las
variables locales de la funcin que ejecuta (almacenados en su pila particular)
Creacin de hilos
Creacin/destruccin de atributos de creacin de hilos
Terminacin/espera a la terminacin de un hilo
Identificacin de hilos
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
Descripcin
attr es el atributo que contiene las caractersticas del hilo creado (vanse atributos de un
hilo en las siguientes transparencias)
start_routine es la funcin que ejecutar el hilo
arg es un puntero a los parmetros iniciales del hilo
En thread se devuelve el identificador del hilo creado si la llamada tiene xito
Valor de retorno:
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
Descripcin
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
Descripcin (continuacin)
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
Descripcin
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
10
Descripcin
Esta funcin suspende la ejecucin del hilo que la invoca hasta que el hilo
identificado por el valor tid finaliza, bien por la invocacin a la funcin
pthread_exit o por estar cancelado
Si status no es NULL, el valor devuelto por el hilo (el argumento de la funcin
pthread_exit, cuando el hilo hijo finaliza) se almacena en la direccin indicada
por status
El valor devuelto es o bien el argumento de la funcin pthread_exit o el valor
PTHREAD_CANCELED si el hilo tid est cancelado
El hilo por el que se espera su terminacin debe estar en estado sincronizable
(joinable state)
Cuando un hilo en este estado termina, no se liberan sus propios recursos (descriptor del
hilo y pila) hasta que otro hilo espere por l
La espera por la terminacin de un hilo para el cual ya hay otro hilo esperando, genera un
error
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
11
Descripcin
Cuando un hilo acepta una peticin de cancelacin, el hilo acta como si se hubiese
realizado la siguiente invocacin pthread_exit(PTHREAD_CANCELED)
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
12
Descripcin
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
13
ASO_PR01_20060228
14
Productor
Consumidor
contador = 9
while (1) {
producir();
while (1) {
extraer();
salida
entrada
insertar();
}
consumir();
}
buffer
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
15
Variables globales
#define N
int
int
20
buffer[N]
entrada, salida, contador;
Programa principal
int main(void) {
pthread_attr_t atrib;
pthread_t
hcons, hprod;
pthread_attr_init(&atrib);
entrada= 0; salida= 0; contador= 0;
pthread_create(&hprod, &atrib, func_proc, NULL);
pthread_create(&hcons, &atrib, func_cons, NULL);
pthread_join(hprod, NULL);
pthread_join(hcons, NULL);
}
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
16
while (1) {
item= producir();
while (1) {
while (contador == 0)
/*bucle vaco: espera */ ;
item= buffer[entrada];
salida= (salida + 1) % N;
contador= contador - 1;
while (contador == N)
/*bucle vaco: espera */ ;
buffer[entrada]= item;
entrada= (entrada + 1) % N;
contador= contador + 1;
}
consumir(item);
}
En este cdigo:
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
17
Productor
Consumidor
contador= contador + 1;
contador= contador 1;
18
Si se supone que:
Cambio de
contexto
Hilo
productor
productor
Operacin
reg1
reg2
contador
inc reg1
consumidor
consumidor
dec reg2
consumidor
productor
EUI-SG/INFOR.UVA.ES
Incorrecto!
ASO_PR01_20060228
19
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
20
Semforos POSIX
POSIX.1b introdujo el tipo de variable semforo sem_t
#include <semaphore.h>
int
int
int
int
int
int
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
21
Semforos POSIX
Productor/Consumidor revisado
#include <semaphore.h>
sem_t mutex, lleno, vacio;
void *func_prod(void *p) {
int item;
while(1) {
item= producir();
sem_wait(&vacio);
sem_wait(&mutex);
buffer[entrada]= item;
entrada= (entrada + 1) % N;
contador= contador + 1;
sem_post(&mutex);
sem_post(&lleno);
}
}
while(1) {
sem_wait(&lleno);
sem_wait(&mutex);
item= buffer[entrada];
salida= (salida + 1) % N;
contador= contador - 1;
sem_post(&mutex);
sem_post(&vacio);
consumir(item);
}
}
...
sem_init(&mutex, 0, 1);
sem_init(&vacio, 0, N);
sem_init(&lleno, 0, 0);
...
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
22
Semforos POSIX
Dos hilos, hilos1 e hilo2 manipulan dos semforos (S1 y S2), inicializados a
1, de acuerdo con el siguiente cdigo
void *hilo1(void *arg) {
...
sem_wait(&S1);
sem_wait(&S2);
...
}
EUI-SG/INFOR.UVA.ES
23
Sincronizacin de pthreads
mutua. Son equivalentes a un semforo que slo puede tomar valor inicial 1
Variables de condicin (contition variables): para la espere de sucesos de
duracin ilimitada. Los hilos se suspenden voluntariamente en estas variables
Los cerrojos de exclusin mutua y las variables de condicin se pueden usar
en todos los hilos del proceso que los crea. Estn pensados para sincronizar
hilos de un mismo proceso, aunque excepcionalmente se pueden compartir
entre procesos
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
24
Los mutex
Funcionamiento
Si el mutex estaba abierto (y por tanto, sin propietario), lo cierra y pasa a ser su propietario
Si el mutex ya estaba cerrado, el hilo que invoca a la operacin de cierre se suspende
Se abre el mutex
Si existan hilos suspendidos (esperando por el cerrojo), se selecciona uno y se despierta, con lo
que puede cerrarlo (y pasar a ser el nuevo propietario)
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
25
Creacin/destruccin de mutexes
#include <pthread.h>
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
pthread_mutex_t mutex= PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_destroy(pthread_mutex_t *mutex);
Permiten crear/destruir un objeto attr con los atributos con los que posteriormente se crear
el mutex
Dichos atributos pueden modificarse mediante funciones especficas
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
26
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
27
Ejemplo
#include <pthread.h>
#include <stdio.h>
int V= 1000;
/* Variable global */
pthread_mutex_t m=
PTHREAD_MUTEX_INITIALIZER;
/* mutex que controla acceso a V */
void *hilo1(void *arg){
int i;
for (i=0; i<1000; i++) {
pthread_mutex_lock(&m);
V= V + 1;
pthread_mutex_unlock(&m);
}
}
EUI-SG/INFOR.UVA.ES
28
Las variables de condicin se llaman as por el hecho de que siempre se usan con una
condicin, es decir, un predicado. Un hilo prueba un predicado y llama a ESPERA si el
predicado es falso. Cuando otro hilo modifica variables que pudieran hacer que se cumpla
la condicin, activa al hilo bloqueado invocando a AVISO
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
29
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
30
hilo2:
cierre(mutex);
...
si (!condicion) entonces
espera(cond, mutex);
...
/* Acceso a variables comunes */
apertura(mutex);
...
EUI-SG/INFOR.UVA.ES
cierre(mutex);
...
/* modificacion variables
involucradas en condicion */
...
aviso_simple(cond);
apertura(mutex);
...
ASO_PR01_20060228
31
Permiten crear/destruir un objeto attr con los atributos con los que posteriormente se crear
la variable de condicin
Dichos atributos pueden modificarse mediante funciones especficas
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
32
(pthread_cond_t *cond
pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond,
pthread_mutex_t *mutex,
const struct timespec *abstime);
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
33
(pthread_cond_t *cond);
EUI-SG/INFOR.UVA.ES
ASO_PR01_20060228
34
hilo 1
pthread_mutex_lock(&m);
if (!condicion)
pthread_cond_wait(&c, &m);
/* Resto de la seccin crtica */
pthread_mutex_unlock(&m);
hilo 2
pthread_mutex_lock(&m);
...
/* Se altera la condicin */
pthread_cond_signal(&c);
pthread_mutex_unlock(&m);
hilo 2
pthread_mutex_lock(&m);
while
(!condicion)
pthread_cond_wait(&c, &m);
/* Resto de la seccin crtica */
pthread_mutex_unlock(&m);
EUI-SG/INFOR.UVA.ES
pthread_mutex_lock(&m);
...
/* Se altera la condicin */
pthread_cond_broadcast(&c);
pthread_mutex_unlock(&m);
ASO_PR01_20060228
35