La concurrència és un concepte clau en la programació moderna, especialment en llenguatges com Haskell, que ofereixen eines poderoses per gestionar múltiples tasques simultànies. En aquest tema, explorarem com Haskell maneja la concurrència, incloent-hi les primitives bàsiques, les biblioteques i els patrons comuns.

Objectius del Tema

  • Entendre els conceptes bàsics de la concurrència.
  • Aprendre a utilitzar les primitives de concurrència en Haskell.
  • Explorar les biblioteques de concurrència més utilitzades.
  • Implementar exemples pràctics de programes concurrents.

Conceptes Bàsics de Concurrència

Què és la Concurrència?

La concurrència és la capacitat d'un programa per executar múltiples tasques al mateix temps. Això pot millorar l'eficiència i la capacitat de resposta d'un programa, especialment en sistemes amb múltiples nuclis de CPU.

Concurrència vs Paral·lelisme

  • Concurrència: Es refereix a la descomposició d'un programa en parts que poden ser executades de manera independent. No implica necessàriament que aquestes parts s'executin simultàniament.
  • Paral·lelisme: Es refereix a l'execució simultània de múltiples tasques en diferents nuclis de CPU.

Primitives de Concurrència en Haskell

forkIO

La funció forkIO és una de les primitives més bàsiques per crear un nou fil d'execució (thread) en Haskell.

import Control.Concurrent

main :: IO ()
main = do
    forkIO $ putStrLn "Hello from the new thread!"
    putStrLn "Hello from the main thread!"

Explicació

  • forkIO pren una acció IO i la executa en un nou fil d'execució.
  • En l'exemple anterior, el missatge "Hello from the new thread!" es pot imprimir abans o després del missatge "Hello from the main thread!", depenent de l'ordre d'execució dels fils.

MVar

MVar és una variable mutable que pot ser utilitzada per compartir dades entre fils de manera segura.

import Control.Concurrent
import Control.Concurrent.MVar

main :: IO ()
main = do
    mvar <- newEmptyMVar
    forkIO $ do
        putStrLn "Child thread: Putting value into MVar"
        putMVar mvar "Hello from MVar"
    value <- takeMVar mvar
    putStrLn $ "Main thread: Got value from MVar: " ++ value

Explicació

  • newEmptyMVar crea un MVar buit.
  • putMVar posa un valor en el MVar.
  • takeMVar llegeix i elimina el valor del MVar.

Biblioteques de Concurrència

async

La biblioteca async proporciona una interfície més alta per treballar amb concurrència.

import Control.Concurrent.Async

main :: IO ()
main = do
    a <- async $ do
        threadDelay 1000000
        putStrLn "Hello from async"
    putStrLn "Hello from main"
    wait a

Explicació

  • async crea una acció asíncrona.
  • wait espera que l'acció asíncrona acabi.

STM (Software Transactional Memory)

STM és una altra eina poderosa per gestionar la concurrència en Haskell.

import Control.Concurrent.STM

main :: IO ()
main = do
    tv <- atomically $ newTVar 0
    atomically $ writeTVar tv 42
    value <- atomically $ readTVar tv
    putStrLn $ "Value: " ++ show value

Explicació

  • atomically executa una transacció STM.
  • newTVar, writeTVar i readTVar són operacions sobre variables transaccionals.

Exercicis Pràctics

Exercici 1: Crear un Fil d'Execució

Crea un programa que utilitzi forkIO per crear un nou fil d'execució que imprimeixi un missatge després d'un retard de 2 segons.

Solució

import Control.Concurrent

main :: IO ()
main = do
    forkIO $ do
        threadDelay 2000000
        putStrLn "Hello from the new thread after 2 seconds!"
    putStrLn "Hello from the main thread!"
    threadDelay 3000000  -- Wait to ensure the new thread finishes

Exercici 2: Utilitzar MVar per Compartir Dades

Crea un programa que utilitzi MVar per compartir un valor entre dos fils d'execució.

Solució

import Control.Concurrent
import Control.Concurrent.MVar

main :: IO ()
main = do
    mvar <- newEmptyMVar
    forkIO $ do
        putStrLn "Child thread: Putting value into MVar"
        putMVar mvar "Hello from MVar"
    value <- takeMVar mvar
    putStrLn $ "Main thread: Got value from MVar: " ++ value

Resum

En aquest tema, hem explorat els conceptes bàsics de la concurrència en Haskell, incloent-hi les primitives bàsiques com forkIO i MVar, així com biblioteques més avançades com async i STM. Hem vist exemples pràctics i hem proporcionat exercicis per reforçar els conceptes apresos. La concurrència és una eina poderosa que pot millorar significativament l'eficiència i la capacitat de resposta dels programes Haskell.

© Copyright 2024. Tots els drets reservats