Sobes.tech
Middle

¿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.