¿Cómo se puede sincronizar la interacción entre hilos?
sobes.tech AI
Respuesta de la IA
Existen varios mecanismos principales para la sincronización y la interacción entre hilos en C/C++:
-
Mutexes (Mutexes): Garantizan acceso exclusivo a un recurso compartido. El hilo que adquiere el mutex bloquea a los demás hasta que lo libera.
#include <mutex> std::mutex my_mutex; void my_thread_function() { my_mutex.lock(); // Adquirir el mutex // Trabajar con el recurso compartido my_mutex.unlock(); // Liberar el mutex }O usando RAII:
#include <mutex> #include <lock_guard> std::mutex my_mutex; void my_thread_function() { std::lock_guard<std::mutex> lock(my_mutex); // Adquirir el mutex al crear el objeto // Trabajar con el recurso compartido // El mutex se libera automáticamente al salir del ámbito } -
Semáforos (Semaphores): Generalización de los mutexes. Mantienen un contador que permite a un número determinado de hilos acceder simultáneamente al recurso.
#include <semaphore.h> // Para semáforos POSIX #include <windows.h> // Para semáforos en Windows sem_t my_semaphore; // Semáforo POSIX void my_thread_function() { sem_wait(&my_semaphore); // Disminuir el contador del semáforo, bloquear si es 0 // Trabajar con el recurso sem_post(&my_semaphore); // Aumentar el contador del semáforo }(Nota: La estándar C++ no incluye semáforos directamente, pero están disponibles a través de bibliotecas del sistema o implementaciones de terceros.)
-
Variables de condición (Condition Variables): Se usan para que un hilo espere a que ocurra una condición específica, liberando el mutex en el proceso. Otro hilo puede notificar que la condición se ha cumplido.
#include <mutex> #include <condition_variable> std::mutex my_mutex; std::condition_variable my_cv; bool condition_met = false; void waiting_thread() { std::unique_lock<std::mutex> lock(my_mutex); my_cv.wait(lock, []{ return condition_met; }); // Esperar a que se cumpla la condición // La condición se ha cumplido, trabajar con el recurso } void notifying_thread() { std::unique_lock<std::mutex> lock(my_mutex); condition_met = true; lock.unlock(); // Liberar el mutex antes de notificar (opcional, pero recomendable) my_cv.notify_one(); // Notificar a un hilo en espera // o // my_cv.notify_all(); // Notificar a todos los hilos en espera } -
Operaciones atómicas (Atomic Operations): Permiten realizar operaciones simples sobre variables (como incremento, decremento) como una acción indivisible, sin necesidad de bloquear explícitamente con un mutex.
#include <atomic> std::atomic<int> counter(0); void my_thread_function() { counter++; // Incremento atómico // O: // counter.fetch_add(1); } -
Bloques de lectura-escritura (Shared Mutexes): Permiten que varios hilos lean datos simultáneamente, pero solo un hilo puede escribir.
#include <shared_mutex> // C++17 y superior std::shared_mutex my_shared_mutex; void read_thread() { my_shared_mutex.lock_shared(); // Adquirir para lectura // Leer datos my_shared_mutex.unlock_shared(); // Liberar para lectura } void write_thread() { my_shared_mutex.lock(); // Adquirir para escritura (exclusivo) // Escribir datos my_shared_mutex.unlock(); // Liberar para escritura } -
Barrera (Barriers): Permiten que un grupo de hilos espere hasta que todos lleguen a un punto determinado en su ejecución, antes de continuar.
#include <barrier> // C++20 std::barrier sync_point(4); // Barrera para 4 hilos void my_thread_function() { // Trabajo antes de la barrera sync_point.arrive_and_wait(); // Esperar a que todos lleguen a la barrera // Trabajo después de la barrera }
La elección de un mecanismo específico depende de la naturaleza de la interacción y los recursos compartidos.