Introducció al Multifil
El multifil (multithreading) és una tècnica de programació que permet executar múltiples fils (threads) de manera concurrent dins d'un mateix procés. Això pot millorar significativament el rendiment d'una aplicació, especialment en sistemes amb múltiples nuclis de CPU.
Conceptes Clau
- Fil (Thread): Un fil és la unitat més petita d'execució que pot ser gestionada pel sistema operatiu.
- Procés: Un procés és un programa en execució que pot contenir múltiples fils.
- Concurrència: La capacitat d'executar múltiples tasques al mateix temps.
- Paral·lelisme: L'execució simultània de múltiples tasques en diferents nuclis de CPU.
Creació de Fils en C++
En C++, la biblioteca <thread>
proporciona les eines necessàries per treballar amb fils. A continuació es mostra un exemple bàsic de com crear i gestionar fils.
Exemple Bàsic
#include <iostream> #include <thread> // Funció que serà executada en un fil separat void funcioFil() { std::cout << "Hola des del fil!" << std::endl; } int main() { // Crear un fil que executa la funció 'funcioFil' std::thread fil(funcioFil); // Esperar que el fil acabi fil.join(); std::cout << "Hola des del fil principal!" << std::endl; return 0; }
Explicació del Codi
- Incloure la Biblioteca
<thread>
: Necessària per treballar amb fils. - Funció
funcioFil
: Aquesta funció serà executada en un fil separat. - Crear un Fil: Utilitzem el constructor de
std::thread
per crear un nou fil que executafuncioFil
. - Esperar que el Fil Acabi: Utilitzem
join()
per esperar que el fil acabi abans de continuar amb el fil principal.
Sincronització de Fils
Quan múltiples fils accedeixen a recursos compartits, és crucial sincronitzar-los per evitar condicions de carrera (race conditions). La biblioteca <mutex>
proporciona mecanismes per a la sincronització.
Exemple amb std::mutex
#include <iostream> #include <thread> #include <mutex> std::mutex mtx; void funcioFil(int id) { // Bloquejar el mutex mtx.lock(); std::cout << "Fil " << id << " està executant" << std::endl; // Desbloquejar el mutex mtx.unlock(); } int main() { std::thread fils[5]; // Crear 5 fils for (int i = 0; i < 5; ++i) { fils[i] = std::thread(funcioFil, i); } // Esperar que tots els fils acabin for (int i = 0; i < 5; ++i) { fils[i].join(); } return 0; }
Explicació del Codi
- Incloure la Biblioteca
<mutex>
: Necessària per treballar amb mutex. - Crear un
std::mutex
: Un objecte mutex per a la sincronització. - Bloquejar i Desbloquejar el Mutex: Utilitzem
mtx.lock()
imtx.unlock()
per assegurar que només un fil accedeixi a la secció crítica al mateix temps.
Exercicis Pràctics
Exercici 1: Crear i Gestionar Fils
Descripció: Escriu un programa que creï tres fils, cadascun dels quals imprimeixi un missatge diferent.
Solució:
#include <iostream> #include <thread> void funcioFil1() { std::cout << "Fil 1 està executant" << std::endl; } void funcioFil2() { std::cout << "Fil 2 està executant" << std::endl; } void funcioFil3() { std::cout << "Fil 3 està executant" << std::endl; } int main() { std::thread fil1(funcioFil1); std::thread fil2(funcioFil2); std::thread fil3(funcioFil3); fil1.join(); fil2.join(); fil3.join(); return 0; }
Exercici 2: Sincronització amb std::mutex
Descripció: Modifica l'exemple anterior per utilitzar un std::mutex
per sincronitzar l'accés a la consola.
Solució:
#include <iostream> #include <thread> #include <mutex> std::mutex mtx; void funcioFil(int id) { mtx.lock(); std::cout << "Fil " << id << " està executant" << std::endl; mtx.unlock(); } int main() { std::thread fils[3]; for (int i = 0; i < 3; ++i) { fils[i] = std::thread(funcioFil, i + 1); } for (int i = 0; i < 3; ++i) { fils[i].join(); } return 0; }
Errors Comuns i Consells
- Oblidar
join()
: Si no esperes que els fils acabin ambjoin()
, el programa pot acabar abans que els fils hagin completat la seva execució. - Condicions de Carrera: Sempre utilitza mecanismes de sincronització com
std::mutex
quan múltiples fils accedeixen a recursos compartits. - Bloqueig de Mutex: Assegura't de desbloquejar el mutex després d'usar-lo per evitar bloquejos (deadlocks).
Conclusió
El multifil és una tècnica poderosa per millorar el rendiment de les aplicacions, però requereix una gestió acurada per evitar problemes de concurrència. Amb els conceptes i exemples proporcionats, hauríeu de tenir una bona base per començar a treballar amb fils en C++.
Curs de Programació en C++
Mòdul 1: Introducció al C++
- Introducció al C++
- Configuració de l'Entorn de Desenvolupament
- Sintaxi i Estructura Bàsica
- Variables i Tipus de Dades
- Entrada i Sortida
Mòdul 2: Estructures de Control
Mòdul 3: Funcions
- Introducció a les Funcions
- Paràmetres de Funció i Tipus de Retorn
- Sobrecàrrega de Funcions
- Recursivitat
Mòdul 4: Arrays i Strings
Mòdul 5: Punteres i Referències
- Introducció als Punteres
- Aritmètica de Punteres
- Punteres i Arrays
- Referències
- Assignació Dinàmica de Memòria
Mòdul 6: Programació Orientada a Objectes
- Introducció a la POO
- Classes i Objectes
- Constructors i Destructors
- Herència
- Polimorfisme
- Encapsulació i Abstracció
Mòdul 7: Temes Avançats
- Plantilles
- Gestió d'Excepcions
- Entrada/Sortida de Fitxers
- Biblioteca de Plantilles Estàndard (STL)
- Expressions Lambda
- Multifil