You are on page 1of 5

Introduccin a las hebras

En programacin secuencial se realizan programas con un nico ujo o hebra de


control. En un programa de estas caractersticas el control siempre se encuentra en
el propio programa, en la ejecucin de llamadas a funciones, o en el ncleo del
sistema operativo.

Los procesos tradicionales de un sistema operativo (p.e. UNIX) tienen una nica
hebra de control denida en su espacio de direcciones. Por otra parte, cuando un
proceso crea otro proceso, el proceso padre e hijo pueden compartir algunas de sus
variables y otros datos o tener espacios de direcciones completamente
independientes. Los procesos que comparten completamente el espacio de
direcciones con su proceso
padre se denominan procesos ligeros ya que tal comparticin reduce
substancialmente el tiempo necesario para crear un proceso hijo o para cambiar el
contexto entre procesos.

Un sistema operativo construido en base a un ncleo que proporcione procesos
ligeros y cuyos mecanismos de intercomunicacin entre procesos asuman dicho
esquema es la base ms adecuada para desarrollar software de estaciones de
trabajo. El cdigo que sirve para administrar los recursos de dicho sistema (p.e.
cheros, E/S, CPUs virtuales, etc.) se suele ejecutar en un espacio comn de
direcciones que pertenece al ncleo. Como es sabido, en el ncleo no existen
procesos independientes, sin embargo, los servicios aludidos suelen ser
encapsulados independientemente y comparten el mismo espacio de direcciones.
Los sistemas operativos modernos incluyen el concepto de procesos ligeros para
realizar los servicios que proporcionan. Tales procesos tienen acceso a las tablas y
estructuras de datos del sistema y sin contar con ellos muchos de los servicios de
los sistemas no podran ser implementados.

El concepto de multiprogramacin con diferentes hebras de control se deriva de
cualquier programa que utilice dos o ms procesos concurrentes que compartan
datos en un espacio comn de direcciones. Un proceso servidor, en un SGBD
distribuido, que cree una copia de s mismo para servir cada peticin de un cliente
diferente es un ejemplo de sistema con mltiples hebras de control.

La diferencia entre programar con mltiples hebras y mltiples procesos es doble:
independencia y comunicacin. En un programa con mltiples procesos, la
separacin entre los procesos es implcita, sin embargo la comunicacin entre los
procesos necesita de una mayor
atencin del programador. En uno con mltiples hebras, la comunicacin entre las
hebras es fcil ya que se realiza a travs de memoria comn, sin embargo,
garantizar la independencia de las hebras, mediante los mecanismos de
sincronizacin apropiados, resulta ms complicado.










1.1. Creando hebras en Python

La forma de crear hebras en Python es extendiendo la clase Thread.

Heredando de la clase Thread

Seguimos los siguientes pasos:
1. Creamos una clase que extienda a la clase Thread y redena el mtodo pblico
run. El mtodo run es el cdigo que la hebra va a ejecutar cuando sea lanzada. El
constructor de la clase (mtodo A1) tambin se redene, permitiendo as asignar
un nombre a la hebra (cuando sta sea inicializada):


# -*- coding: iso-8859-15 -*-
import threading
# Variable cerrojo
cerrojo = threading.Lock()
# Clase A1
class A1 (threading.Thread):
# Constructor
def __init__(self, nombre, siesta, args):
Thread.__init__(self)
self.setName(nombre)
self._siesta = siesta
# Metodo run
def run (self):
print 'Hola, soy %s' % this.getName()
if self._siesta > 0:
cerrojo.acquire()
else:
print 'Me fastidiaron la siesta!'

2. En otro lugar creamos una instancia de la clase denida. De esta forma se crea
un objeto hebra (una instancia de una subclase de Thread).

3. Llamamos al mtodo start para la instancia creada. Esta llamada hace que el
mtodo run se ejecute como una nueva hebra.

# -*- coding: iso-8859-15 -*-
import threading
# Variable cerrojo
cerrojo = threading.Lock()
# Clase A1
class A1 (threading.Thread):
# Constructor
def __init__(self, nombre, siesta, args):
threading.Thread.__init__(self)
self.setName(nombre)
self._siesta = siesta
# Metodo run
def run (self):
print 'Hola, soy %s' % self.getName()
if self._siesta > 0:
cerrojo.acquire()
else:
print 'Me fastidiaron la siesta!'

a1 = A1("Hebra_01", 0, [])
a1.start()

Normalmente podemos ordenar un poco el cdigo para lanzar varias instancias de
la hebra:

# -*- coding: iso-8859-15 -*-
import threading
# Clase A1
class A1 (threading.Thread):
# Constructor
def __init__(self, nombre, siesta, cerrojo, args):
threading.Thread.__init__(self)
self.setName(nombre)
self._siesta = siesta
self._cerrojo = cerrojo
# Metodo run
def run (self):
print 'Hola, soy %s' % self.getName()
if self._siesta > 0:
self._cerrojo.acquire()
else:
print 'Me fastidiaron la siesta!'

# Funcion main del programa
if __name__== "__main__":
# Variable cerrojo
cerrojo = threading.Lock()
lista = []
# Que pasa si en lugar de 0 pasamos un 1?
for i in range(100):
lista.append(A1("Hebra_%.2d" % i, 0, cerrojo, []))
for a in lista:
a.start()

1.2. Clases y mtodos asociados a una hebra

Una hebra en Python es una clase que hereda de Thread, Thread es la clase de alto
nivel de Python para manejar hebras. Existen, sin embargo, varias clases
adicionales que sirven para realizar distintas operaciones sobre hebras:

Thread

La clase Thread permite la ejecucin concurrente de trozos de cdigo y su
manipulacin.

Existen dos formas de utilizarlas, el primero es pasar como argumento una funcin,
la cual se ejecutar simtricamente con respecto a otras hebras del proceso. La
otra, ms comn, es extender la clase, y en concreto, el mtodo run (tal y como se
ha visto en el apartado anterior). Sus mtodos son los siguientes:

start() Lanza la hebra. Internamente llama al mtodo run.
run() Indica el cdigo que se ejecutar cuando se lance la hebra.
join() Espera a que la hebra termine, salvo cuando hay algn temporizador
(timeout).
getName() Devuelve el nombre de la hebra.
setName() Cambia el nombre de la hebra.
isAlive() Devuelve si la hebra est viva (ejecutndose) o no.
isDaemon() Devuelve el ag de demonio.
setDaemon() Activa el ag de demonio de la hebra. Un programa en

Python puede salir solamente cuando no hay hebras de demonio en su interior.

Lock

Esta clase implementa un mtodo sencillo de cerrojo (se puede ver un ejemplo en
el cdigo anterior). Solamente tiene dos mtodos:

acquire(blocking = 1) Adquiere un cerrojo, bloqueando el sistema o
desbloquendolo.

Tiene un parmetro opcional.

release() Abre un cerrojo.

RLock

Esta clase implementa un cerrojo reentrante. Es igual que el sistema de la clase
Lock, salvo que este cerrojo tiene incorporado un mtodo para controlar algoritmos
recursivos.

Solamente tiene dos mtodos:
acquire(blocking = 1) Adquiere un cerrojo, bloqueando el sistema o
desbloquendolo.

Tiene un parmetro opcional.

release() Abre un cerrojo.

Condition Una variable condicin est asociada siempre con algn tipo de cerrojo
(el cual se le suele pasar al constructor de la clase, siendo de tipo Lock o RLock).
Tiene los siguientes
mtodos:

acquire(*args) Adquiere un cerrojo.
release() Abre un cerrojo.
wait(timeout) Espera hasta que haya alguna noticacin o se pase el tiempo
indicado en la funcin. Este mtodo abre el cerrojo y espera un notify() o un
notifyAll().
notify() Despierta una hebra que est esperando esta condicin (si la hay). Este
mtodo debe ser llamado slo cuando esta hebra haya adquirido el cierre.
notifyAll() Despierta a todas las hebras que estn esperando esta condicin.

Semaphore

Implementa un semforo, tiene dos mtodos: acquire y release.

Event

Implementa un sistema sencillo de eventos entre hebras. Los mtodos que tiene
asociados son los siguientes:

isSet() Devuelve true si el ag interno es verdadero.
set() Cambia a true el ag interno.
clear() Cambia a false el ag interno.
wait() Espera hasta que el ag interno sea true.

Timer

Esta clase es una hebra de ejemplo que extiende a la clase Thread. Ejecuta una
funcin despus de que pase un tiempo:

def hola():
print "hola mundo!"
t = Timer(30.0, hola)
t.start() # tras 30 segundos aparecer\'a en pantalla: "hola
mundo!"

Para utilizar cualquiera de estas clases ha de importarse el paquete threading. Este
paquete es tambin un objeto con unos mtodos asociados. Por ejemplo, podemos
conocer el nmero de hebras que se estn ejecutando en este momento
escribiendo:

threading.activeCount()

La documentacin detallada de todos estos mtodos se encuentra en:
http://docs.python.org/lib/module-threading.html

You might also like