La concurrència és un concepte clau en la programació moderna, especialment quan es tracta de millorar el rendiment i la capacitat de resposta de les aplicacions. En aquest tema, explorarem com Python gestiona la concurrència mitjançant fils (threads) i processos (processes).
Objectius del Tema
- Entendre la diferència entre fils i processos.
- Aprendre a crear i gestionar fils en Python.
- Aprendre a crear i gestionar processos en Python.
- Conèixer les eines i biblioteques que Python ofereix per treballar amb concurrència.
- Diferència entre Fils i Processos
Fils (Threads)
- Definició: Un fil és la unitat més petita d'execució dins d'un procés. Els fils d'un mateix procés comparteixen el mateix espai de memòria.
- Avantatges:
- Menor sobrecàrrega en la creació i destrucció.
- Compartició de memòria fàcil entre fils.
- Desavantatges:
- Potencials problemes de sincronització (race conditions).
- Limitació del GIL (Global Interpreter Lock) en Python, que impedeix l'execució concurrent de múltiples fils en un sol procés.
Processos (Processes)
- Definició: Un procés és una instància d'un programa en execució. Cada procés té el seu propi espai de memòria.
- Avantatges:
- Execució realment paral·lela en sistemes multiprocessador.
- Aïllament de memòria, evitant problemes de sincronització.
- Desavantatges:
- Major sobrecàrrega en la creació i destrucció.
- Comunicació entre processos més complexa.
- Treballant amb Fils en Python
Creació de Fils
Python proporciona el mòdul threading
per treballar amb fils. A continuació, es mostra un exemple bàsic de com crear i executar un fil:
import threading def treballar(): print("El fil està treballant") # Crear un fil fil = threading.Thread(target=treballar) # Iniciar el fil fil.start() # Esperar que el fil acabi fil.join()
Sincronització de Fils
Per evitar problemes de sincronització, podem utilitzar bloquejos (locks):
import threading bloqueig = threading.Lock() def treballar(): with bloqueig: print("El fil està treballant amb bloqueig") fil = threading.Thread(target=treballar) fil.start() fil.join()
- Treballant amb Processos en Python
Creació de Processos
Python proporciona el mòdul multiprocessing
per treballar amb processos. A continuació, es mostra un exemple bàsic de com crear i executar un procés:
import multiprocessing def treballar(): print("El procés està treballant") # Crear un procés procés = multiprocessing.Process(target=treballar) # Iniciar el procés procés.start() # Esperar que el procés acabi procés.join()
Comunicació entre Processos
Podem utilitzar cues (queues) per comunicar-nos entre processos:
import multiprocessing def treballar(cua): cua.put("Missatge del procés") # Crear una cua cua = multiprocessing.Queue() # Crear un procés procés = multiprocessing.Process(target=treballar, args=(cua,)) # Iniciar el procés procés.start() # Esperar que el procés acabi procés.join() # Llegir el missatge de la cua missatge = cua.get() print(missatge)
- Comparació entre Fils i Processos
Característica | Fils | Processos |
---|---|---|
Espai de Memòria | Compartit | Aïllat |
Creació/Destrucció | Ràpida | Més lenta |
Comunicació | Fàcil (memòria compartida) | Més complexa (IPC) |
Execució Paral·lela | Limitada pel GIL | Realment paral·lela |
Sincronització | Necessària (locks) | Menys necessària |
Exercicis Pràctics
Exercici 1: Crear i Gestionar Fils
Crea un programa que iniciï tres fils, cadascun dels quals imprimeixi un missatge diferent. Assegura't que tots els fils acabin abans que el programa finalitzi.
Exercici 2: Crear i Gestionar Processos
Crea un programa que iniciï dos processos, cadascun dels quals imprimeixi un missatge diferent. Utilitza una cua per enviar un missatge des de cada procés al procés principal.
Exercici 3: Sincronització de Fils
Crea un programa que iniciï dos fils que incrementin una variable compartida 1000 vegades cadascun. Utilitza un bloqueig per assegurar-te que la variable es modifica de manera segura.
Solucions
Solució 1: Crear i Gestionar Fils
import threading def treballar(missatge): print(missatge) fils = [] missatges = ["Fil 1", "Fil 2", "Fil 3"] for missatge in missatges: fil = threading.Thread(target=treballar, args=(missatge,)) fils.append(fil) fil.start() for fil in fils: fil.join()
Solució 2: Crear i Gestionar Processos
import multiprocessing def treballar(missatge, cua): print(missatge) cua.put(f"Missatge del {missatge}") cua = multiprocessing.Queue() processos = [] missatges = ["Procés 1", "Procés 2"] for missatge in missatges: procés = multiprocessing.Process(target=treballar, args=(missatge, cua)) processos.append(procés) procés.start() for procés in processos: procés.join() while not cua.empty(): print(cua.get())
Solució 3: Sincronització de Fils
import threading bloqueig = threading.Lock() variable_compartida = 0 def incrementar(): global variable_compartida for _ in range(1000): with bloqueig: variable_compartida += 1 fils = [threading.Thread(target=incrementar) for _ in range(2)] for fil in fils: fil.start() for fil in fils: fil.join() print(f"Valor final de la variable compartida: {variable_compartida}")
Conclusió
En aquest tema, hem explorat els conceptes de concurrència en Python mitjançant fils i processos. Hem après a crear i gestionar fils i processos, així com a sincronitzar fils per evitar problemes de concurrència. També hem vist com comunicar-nos entre processos utilitzant cues. La comprensió d'aquests conceptes és fonamental per escriure aplicacions eficients i responsives.
Curs de Programació en Python
Mòdul 1: Introducció a Python
- Introducció a Python
- Configuració de l'Entorn de Desenvolupament
- Sintaxi de Python i Tipus de Dades Bàsics
- Variables i Constants
- Entrada i Sortida Bàsiques
Mòdul 2: Estructures de Control
Mòdul 3: Funcions i Mòduls
- Definició de Funcions
- Arguments de Funció
- Funcions Lambda
- Mòduls i Paquets
- Visió General de la Biblioteca Estàndard
Mòdul 4: Estructures de Dades
Mòdul 5: Programació Orientada a Objectes
Mòdul 6: Gestió de Fitxers
- Lectura i Escriptura de Fitxers
- Treballant amb Fitxers CSV
- Gestió de Dades JSON
- Operacions amb Fitxers i Directoris
Mòdul 7: Gestió d'Errors i Excepcions
Mòdul 8: Temes Avançats
- Decoradors
- Generadors
- Gestors de Context
- Concurrència: Fils i Processos
- Asyncio per a Programació Asíncrona
Mòdul 9: Proves i Depuració
- Introducció a les Proves
- Proves Unitàries amb unittest
- Desenvolupament Guiat per Proves
- Tècniques de Depuració
- Ús de pdb per a la Depuració
Mòdul 10: Desenvolupament Web amb Python
- Introducció al Desenvolupament Web
- Conceptes Bàsics del Framework Flask
- Construcció d'APIs REST amb Flask
- Introducció a Django
- Construcció d'Aplicacions Web amb Django
Mòdul 11: Ciència de Dades amb Python
- Introducció a la Ciència de Dades
- NumPy per al Càlcul Numèric
- Pandas per a la Manipulació de Dades
- Matplotlib per a la Visualització de Dades
- Introducció al Machine Learning amb scikit-learn