Как использовать переменную условия - PullRequest
9 голосов
/ 01 июня 2011

В книге «Интерфейс программирования Linux» есть фрагмент кода (производитель / потребитель), чтобы показать, как работает переменная условия:

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

static int avail = 0;

while (TRUE) {
    s = pthread_mutex_lock(&mtx);

    while (avail == 0) {   /* Wait for something to consume */
       s = pthread_cond_wait(&cond, &mtx);
    }

    while (avail > 0) {   /* Consume all available units */ 
        avail--;
    }

    s = pthread_mutex_unlock(&mtx);
}

Почему мы используем pthread_mutex_lock в while?почему мы не используем его в if?

1 Ответ

12 голосов
/ 01 июня 2011

Поскольку pthread_cond_signal () разрешено вызывать более одного потока, ожидающего переменную условия.Поэтому вы должны дважды проверить условие, как только проснетесь, потому что какой-то другой поток мог проснуться и изменить его перед вами.

Если вы знаете, что вас ожидает только один поток, и вы уверены, что никто небудущее когда-нибудь изменит код в другом месте программы, чтобы добавить еще один ожидающий поток, тогда вы можете использовать if.Но вы никогда не узнаете это наверняка, поэтому всегда используйте while.

[обновление]

. Как отмечает ниндзя в комментарии, мой ответ неполон, так как я не упомянул "ложные пробуждения",Например, стандарт POSIX проясняет, что, если ожидающий поток получает сигнал (например, через kill ()), pthread_cond_wait () может вернуть 0, даже если никакой другой поток не сигнализировал переменную условия.Стандарт (на мой взгляд) неоднозначен относительно того, можно ли разбудить ожидающий поток без всякой причины ... Но суть в следующем: Всегда использовать while, а не if.

...