es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Notificar una variable de condición garantiza la activación de un hilo con una condición/predicado exitoso si existe alguno?

La información que he encontrado en cppreference es vaga al respecto, así que estoy preguntando aquí. Digamos que tengo dos hilos esperando en una condición, uno con un predicado verdadero y el otro con uno falso (por ejemplo, condition.wait(lock, [=]{ return some_condition; })). El hilo principal decide notificar aleatoriamente a uno de ellos con cond.notify_one().

Supongamos que el hilo en espera seleccionado es aquel donde el predicado es falso. ¿El hilo va a notificar implícitamente al siguiente (si es que quedan), o estará condenado a esperar hasta una falsa alerta?

En caso de que solo se despierte a un solo hilo sin importar si su condición tiene éxito o falla, ¿cuál sería una buena manera para que el primer hilo intente despertar al siguiente de forma exitosa? Una solución ingenua:

c++
condition.wait(lock, [=] {
if (!some_condition) condition.notify_one();
return some_condition;
});

Además de ser una pessimization, la “ola de notificaciones” puede notificar repetidamente a los mismos hilos, lo cual es ineficiente y nunca termina en caso de que ningún hilo tenga predicados exitosos. Un notify_all() no funcionará, porque podríamos despertar accidentalmente a varios hilos que satisfacen la condición, mientras que solo queremos que pase como máximo uno.

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Si el hilo de espera seleccionado es aquel en el que el predicado es falso, estará condenado a esperar hasta que haya una llamada de despertar espurio. La función notify_one() no garantiza qué hilo será despertado, y es posible que el predicado para el hilo despertado siga siendo falso, lo que resultaría en otra espera.

    Una mejor manera de manejar esta situación sería utilizar un condicional separado para cada predicado. De esta manera, cuando el hilo principal notifique uno de los condicionales, solo los hilos que esperan en ese predicado en particular se despertarán. Por ejemplo:

    “`c++
    std::condition_variable true_cond;
    std::condition_variable false_cond;
    std::mutex mutex;

    // Hilo 1:
    std::unique_lock lock(mutex);
    true_cond.wait(lock, []{ return some_condition; });
    // hacer algo

    // Hilo 2:
    std::unique_lock lock(mutex);
    false_cond.wait(lock, []{ return !some_condition; });
    // hacer algo más

    // Hilo principal:
    std::unique_lock lock(mutex);
    if (some_condition) {
    true_cond.notify_one();
    } else {
    false_cond.notify_one();
    }
    “`

    Esto asegura que solo el hilo que espera en el predicado correcto será despertado y eliminará la necesidad de que el primer hilo intente despertar al siguiente.

Comments are closed.