Está en la página 1de 31

PROGRAMACIN

CONCURRENTE EN LENGUAJES
FUNCIONALES:

CONCURRENT HASKELL

Rafael lvarez Lpez


Fernando vila Ferrer

NDICE

1. INTRODUCCIN
1.1 Motivacin y Orgenes
1.2 Concurrencia y lenguajes funcionales
2. CONCURRENT HASKELL
2.1 Procesos
2.2 Sincronizacin y comunicacin
2.3 Semforos
2.4 Otras operaciones concurrentes
2.5 Productor/consumidor
2.6 Canales

3. CONCLUSIONES
4. REFERENCIAS

1. INTRODUCCIN

La necesidad de ofrecer concurrencia en el acceso a


los recursos computacionales se remonta a los
primeros sistemas operativos.
Aprovechar al mximo los recursos computacionales
fue una necesidad apremiante, sobre todo en la poca
en que las computadoras eran caras y escasas; el
sistema operativo tena que ofrecer la ejecucin
concurrente y segura de programas de varios
usuarios, que desde distintas terminales utilizaban un
solo procesador, y as surgi la necesidad de
introducir algunos conceptos de programacin
concurrente para programar los sistemas operativos.
3

1.1 Motivacin y Orgenes

Existen sistemas inherentemente concurrentes: los


sistemas reactivos.
Aparte de esta motivacin existen otras dos
motivaciones principales, que de hecho fueron
anteriores en el tiempo a la utilizacin de la
programacin concurrente para la construccin de
sistemas reactivos:
Explotacin de arquitecturas paralelas para obtener
ganancia en la velocidad de ejecucin (Programacin
Paralela).
Mejorar la utilizacin del procesador (Sistemas
Operativos).
4

1.2 Concurrencia y lenguajes


funcionales
Debido

a la propiedad de confluencia
(podemos encontrar dos secuencias de
evaluacin diferentes que parten del mismo
dato de entrada), los lenguajes funcionales
pueden utilizar directamente el paralelismo
implcito. Otra opcin es aadir al lenguaje
ciertas extensiones para especificar la
concurrencia, como es el caso que vamos a
estudiar.
5

2. CONCURRENT HASKELL
Concurrent

Haskell es una extensin del


lenguaje funcional perezoso Haskell para
ofrecer la posibilidad de realizar programas
concurrentes. Concurrent Haskell representa
un nuevo paso que apunta a construir un
puente entre el mundo de los lenguajes
funcionales puros y los lenguajes intensivos
de entrada y salida.
6

Algo ms que una extensin


de haskell :

Consigue integrar la concurrencia en un lenguaje perezoso. Por


ejemplo los procesos pueden comunicarse como estructuras de
datos sin evaluar unos a otros.
Presenta una semntica para Haskell claramente diferenciada
en una capa determinista y una capa concurrente. Las tcnicas
de razonamiento existentes son mantenidas sin modificaciones,
por ejemplo, las transformaciones de programas que preservan
la correccin en un programa Haskell secuencial tambin la
preservarn en un lenguaje Haskell concurrente.
Hay pocas operaciones primitivas nuevas, que son expresivas y
fciles de implementar.

nuevos ingredientes a haskell:


Procesos,

y un mecanismo para gestionarlos.


Estados atmicos mutables, para soportar
comunicacin y cooperacin entre los
procesos.

2.1 Procesos

Concurrent Haskell proporciona la nueva primitiva


forkIO que inicia un proceso concurrente:
forkIO :: IO () -> IO ()
forkIO a , es una accin que toma a otra accin , a,
como su argumento y crea un proceso concurrente
que ejecuta dicha accin. La entrada y salida y
otros efectos laterales realizados por a, son
interpolados de una manera indefinida con aquellos
que siguen el forkIO.
9

Ejemplo1:
import Control.Concurrent
main = forkIO (escribir 'a') >> escribir 'b'
where escribir c = putChar c >> escribir c

10

caractersticas de forkIO :

Como la implementacin de haskell usa evaluacin perezosa,


forkIO necesitar sincronizacin entre procesos, ya que un
proceso puede intentar evaluar un razonamiento que ya est
siendo evaluado por otro proceso, en cuyo caso el primero debe
ser bloqueado hasta que el ltimo complete la evaluacin y
sobrescriba el razonamiento con su valor.
Como tanto el proceso padre como el hijo, pueden cambiar el
mismo estado compartido forkIO introduce inmediatamente el no
determinismo. El problema es que casi todas las aplicaciones
concurrentes interesantes implican el uso del mismo estado
compartido por varios procesos. Por tanto, la solucin correcta
ser proveer mecanismos que permitan la gestin segura de un
estado compartido.
forkIO es asimtrico. Cuando un proceso ejecuta un forkIO crea
un proceso hijo que se ejecuta concurrentemente al padre.
11

2.2 Sincronizacin y
comunicacin
Los

procesos pueden necesitar acceso


exclusivo a algunos objetos como por
ejemplo ficheros. La manera de implementar
este acceso exclusivo requiere una variable
compartida mutable o un semforo.
Para que un proceso pueda leer una cadena
de valores producida por varios procesos es
proporcionando una operacin no
determinista de ordenacin.

12

Type MVar a

Un valor del tipo MVar t, para algn tipo t, es el nombre de una


posicin de memoria que pueda estar vaca o contener un valor
de tipo t. A su vez sobre MVar se pueden realizar las siguientes
operaciones:
newMVar :: IO (MVar a) Crea una nueva MVar
takeMVar :: MVar a -> IO a Bloquea hasta que la posicin sea
no vaca. Entonces lee y devuelve el valor dejando la posicin
vaca.
putMVar :: MVar a -> a -> IO () Escribe un valor en la posicin
especificada. Si existen uno o mas procesos bloqueados en
takeMVar sobre dicha variable, se selecciona uno para que lo
procese. Puede producir error utilizarlo sobre una variable que
ya contenga un valor.
13

MVar
El tipo MVar puede ser usado de tres maneras
diferentes:
Puede ser usado como una versin sncronizada del
tipo MutVar.
Puede ser empleado como un tipo de canal, donde
takeMVar y PutMVar funcionan como recibir y
enviar.
El MVar puede ser usado como un semforo
binario, donde los signal y los waits son
implementados con putMVar y takeMVar
respectivamente.
14

2.3 Semforos
Aunque se puede implementar con un MVar usando
las operaciones putMVar y takeMVar, los semforos
tambien estn implementados en Concurrent
Haskell.
Semforo binario:
data QSem
newQSem :: Int -> IO QSem
waitQSem :: QSem -> IO ()
signalQSem :: QSem -> IO ()
15

2.3 Semforos
Semforos de cantidad general:
data QSemN
newQSemN :: Int -> IO QSemN
waitQSemN :: QSemN -> Int -> IO ()
signalQSemN :: QSemN -> Int -> IO ()

16

2.4 Otras operaciones


concurrentes

forkIO :: IO a -> IO --Crea proceso hijo


threadDelay :: Int -> IO () Dormir durante n microsegundos
newEmptyMVar :: IO (MVar a) Crear Mvar vaco
newMVar :: a -> IO (MVar a) Inicializar MVAr
takeMVar :: MVar a -> IO a take bloqueante
putMVar :: MVar a -> a -> IO () put bloqueante
tryTakeMVar :: MVar a -> IO (Maybe a) take no bloqueante
tryPutMVar :: MVar a -> a -> IO Bool put no bloqueante
isEmptyMVar :: MVar a -> IO Bool -- Test de Mvar vaco
swapMVar :: MVar a -> a -> IO a --- Intercambia el valor de Mvar
17

2.5 Productor/consumidor

MVar puede ser usado para implementar una


conexin entre productor y consumidor. El productor
guarda elementos en el MVar y el consumidor los
saca. El problema es que no hay nada que impida
que el productor escriba un segundo valor antes de
que el consumidor haya sacado el primero.
Este problema se soluciona con un segundo MVar
para manejar confirmaciones entre consumidor y
productor. Llamaremos a la abstraccin resultante
CVar (variable de canal).
18

Productor consumidor
type CVar a = (MVar a,
MVar ())

-- Productor-> consumidor
-- Consumidor -> productor

newCVar :: IO (CVar a)
newCVar = newMVar >>= \ data_var ->
newMVar
>>= \ ack_var ->
putMVar ack_var () >> return (data_var, ack_var)
putCVar :: CVar a -> a -> IO ()
putCVar (data_var,ack_var) val= takeMVar ack_var >> putMVar
data_var val
getCVar :: CVar a -> IO a
getCVar (data_var,ack_var) = takeMVar data_var
putMVar ack_var ()
>> return val

>>= \ val ->


19

2.6 Canales
El

proceso creado por el forkIO y su padre


pueden realizar entrada y salida
independientemente. Podemos pensar en el
estado del sistema como un objeto
conmutable compartido. Por ejemplo, si dos
procesos escriben en el mismo fichero
pueden aparecer situaciones indeseadas.
Pero como ya sabemos, es comn que dos o
ms procesos quieran acceder al mismo
fichero.
20

Canales
Usando MVars podemos definir un nuevo tipo que
llamaremos canal que permitir que mltiples
procesos escriban y lean de l de forma segura.
type Channel a = (MVar (Stream a), -- ltimo ledo
MVar (Stream a)) -- ltimo escrito
newChan :: IO (Channel a)
putChan :: Channel a -> a -> IO
getChan :: Channel a -> IO a

21

Canales

22

El canal est implementado por un par de MVars


que apuntan al ltimo elemento ledo (read end) y al
ltimo elemento escrito (write end) del canal
respectivamente.
Las Mvar del canal proporcionan un mecanismo
mediante el cual las operaciones de put y get
pueden modificar el read end y el write end del
canal.
Los datos en el buffer son almacenados en un
Stream que es un MVar que puede estar vaco (en
cuyo caso no hay datos en el stream) o almacena
un Item.
23

type Stream a = MVar (Item a)


Un Item es simplemente un par de elementos, uno
con el dato y otro apundanto al resto del stream.
data Item a = MkItem a (Stream a)
Un Stream puede ser considerado como una lista
que consiste en alternar Items y Mvars que termina
con un agujero que consiste en un MVar vaco. El
Write end del canal apunta a dicho agujero(Hole).

24

newChan = do { read <- newEmptyMVar ;


write <- newEmptyMVar ;
hole <- newEmptyMVar ;
putMVar read hole ;
putMVar write hole ;
return (read,write) }

25

putChan (read,write) val


= do { new_hole <- newEmptyMVar ;
old_hole <- takeMVar write ;
putMVar write new_hole ;
putMVar old_hole (MkItem val new_hole) }

26

getChan (read,write)
= do { head_var <- takeMVar read ;
MkItem val new_head <- takeMVar head_var ;
putMVar read new_head ;
return val }

27

canal multicast

dupChan :: Channel a -> IO (Channel a)


dupChan (read,write)
= do { new_read <- newEmptyMVar ;
hole <- readMVar write ;
putMVar new_read hole ;
return (new_read, write) }
28

Implementacin de canales en
Concurrent Haskell

data Chan a
newChan :: IO (Chan a)
-- Nuevo canal
writeChan :: Chan a -> a -> IO () --Escribe dato en canal
readChan :: Chan a -> IO a
--Lee un dato del canal
dupChan :: Chan a -> IO (Chan a) --Duplica el canal
unGetChan :: Chan a -> a -> IO () --Devuelve un dato al canal
isEmptyChan :: Chan a -> IO Bool --Comprueba si est vaco
getChanContents :: Chan a -> IO [a] -- lee todo el contenido
writeList2Chan :: Chan a -> [a] -> IO () -- Escribe el contenido
de una lista en el canal

29

3. CONCLUSIONES

Hemos comprobado como Concurrent Haskell


aporta nueva funcionalidad a Haskell.
Aadiendo forkIO y MVars a Haskell damos un salto
cualitativo en cuanto a la cantidad de aplicaciones
que podemos escribir. Las extensiones son
sencillas y simples de describir.
En la actualidad Haskell y sus versiones
concurrentes estn siendo empleados de manera
comercial como herramienta de programacin para
servidores, aportando una nueva manera de
programar potente y elegante.
30

4. REFERENCIAS

http://www.haskell.org
Ruz, B.C.; Gutirrez, F.; Guerrero, P.; Gallardo, J.E.: Razonando con
Haskell. Una introduccin a la Programacin Funcional. Servicio
reprogr. (OC) E.T.S.I.I., Universidad de Mlaga. 2000
http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control.Concu
rrent.html
Tackling the Awkward Squad: monadic input/output, concurrency,
exceptions, and foreign-language calls in Haskell
Simon PEYTON JONES Microsoft Research, Cambridge
simonpj@microsoft.com
http://research.microsoft.com/users/simonpj
Concurrent Haskell
Simon Peyton Jones (University of Glasgow)
Andrew Gordon (University of Cambridge)
Sigbjorn Finne (University of Glasgow)
Notas para la asignatura Programacin Declarativa Avanzada.
Blas Carlos Ruiz Jimnez

31

También podría gustarte