Un hilo es una secuencia de instrucciones que se ejecuta en paralelo con otros hilos dentro del mismo proceso. Los hilos permiten que un programa realice múltiples tareas al mismo tiempo, lo que puede ser útil para mejorar la capacidad de respuesta y la utilización de recursos.
En C++, puedes trabajar con hilos utilizando la biblioteca std::thread
que proporciona el estándar C++. Aquí tienes un ejemplo simple de cómo crear y ejecutar hilos:
#include <iostream>
#include <thread>
void funcionHilo(int id) {
std::cout << "Hola desde el hilo " << id << std::endl;
}
int main() {
std::thread hilo1(funcionHilo, 1); // Crear un hilo y pasar un argumento
std::thread hilo2(funcionHilo, 2);
hilo1.join(); // Esperar a que el hilo1 termine
hilo2.join(); // Esperar a que el hilo2 termine
return 0;
}
Ejemplo 1: Cálculo Paralelo de Suma:
En este ejemplo, utilizamos hilos para calcular la suma de un arreglo de números de manera paralela. Cada hilo suma una parte del arreglo y luego los resultados parciales se combinan para obtener el resultado final.
#include <iostream>
#include <thread>
#include <vector>
#include <numeric>
// Función que suma una parte del arreglo
void sumarParte(const std::vector<int>& numeros, size_t inicio, size_t fin, int& resultadoParcial) {
resultadoParcial = std::accumulate(numeros.begin() + inicio, numeros.begin() + fin, 0);
}
int main() {
const int numElementos = 1000000;
const int numHilos = 4;
std::vector<int> numeros(numElementos, 1);
std::vector<std::thread> hilos(numHilos);
std::vector<int> resultadosParciales(numHilos);
size_t tamParte = numElementos / numHilos;
for (int i = 0; i < numHilos; ++i) {
size_t inicio = i * tamParte;
size_t fin = (i == numHilos - 1) ? numElementos : (i + 1) * tamParte;
hilos[i] = std::thread(sumarParte, std::ref(numeros), inicio, fin, std::ref(resultadosParciales[i]));
}
for (int i = 0; i < numHilos; ++i) {
hilos[i].join();
}
int sumaTotal = std::accumulate(resultadosParciales.begin(), resultadosParciales.end(), 0);
std::cout << "Suma total: " << sumaTotal << std::endl;
return 0;
}
Ejemplo 2: Productor-Consumidor:
En este ejemplo, implementamos el patrón de diseño Productor-Consumidor utilizando hilos. Los productores generan datos y los colocan en un búfer, mientras que los consumidores toman los datos del búfer y los procesan.
#include <iostream>
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
const int tamBuffer = 10;
std::queue<int> buffer;
std::mutex mtx;
std::condition_variable cv;
void productor() {
for (int i = 0; i < 20; ++i) {
std::unique_lock<std::mutex> lock(mtx);
while (buffer.size() == tamBuffer) {
cv.wait(lock);
}
buffer.push(i);
std::cout << "Productor: producido " << i << std::endl;
cv.notify_all();
}
}
void consumidor() {
for (int i = 0; i < 20; ++i) {
std::unique_lock<std::mutex> lock(mtx);
while (buffer.empty()) {
cv.wait(lock);
}
int valor = buffer.front();
buffer.pop();
std::cout << "Consumidor: consumido " << valor << std::endl;
cv.notify_all();
}
}
int main() {
std::thread t1(productor);
std::thread t2(consumidor);
t1.join();
t2.join();
return 0;
}
Pueder ir al artículo principal:
Códigos Sencillos hechos en C++