Как ждать любой условной переменной?

pthread_cond_wait позволяет нам ждать, пока переменная условия не получит сигнал.

Однако есть ли шанс дождаться, пока какая-либо из двух условных переменных не получит сигнал?

Причина, по которой я спрашиваю, заключается в том, что у меня следующая ситуация: у меня есть 42 потока и два возможных предиката, при которых эти потоки могут продолжать свою работу. Они могут продолжать свою работу, если выполняется ЛЮБОЙ из этих двух предикатов.

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

Итак, моя идея состояла в том, чтобы иметь одну условную переменную, которая транслируется всякий раз, когда выполняется второе pred… и еще 42 условных переменных, каждая из которых связана с одним из потоков. Соответствующий из них должен сигнализироваться всякий раз, когда выполняется первое пред.

Но это требует, чтобы потоки просыпались всякий раз, когда сигнализируется ЛЮБАЯ из заданного набора переменных cond... Есть ли шанс добиться этого?


person Community    schedule 30.05.2017    source источник
comment
Я думаю, что 43 потока были бы самым простым подходом: один пул из 42 потоков для массивно-параллельного задания и один пул из одного потока для однопоточного задания. Или, может быть, использовать семафор вместо условной переменной и отправить на семафор соответствующее количество раз.   -  person Andrew Henle    schedule 30.05.2017


Ответы (1)


Нет, вы можете ждать только одну переменную условия.

Однако это нормально. Когда поток пробуждается из pthread_cond_wait(), он должен проверить, действительно ли предикат, которого он ожидает, на самом деле истинен. «ложное пробуждение»).

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

pthread_mutex_lock(&lock);

while (!this_thread_can_proceed(state) && !all_threads_can_proceed(state))
    pthread_cond_wait(&cond, &lock);

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

Какое из этих решений будет работать лучше, зависит от баланса между пробуждением «всех потоков» и «одним потоком» в вашем приложении.

person caf    schedule 31.05.2017
comment
Кажется, ужасное исполнение. AFAIK переключение потоков достаточно дорого. Гарантия O(количества потоков) бесполезных переключений контекста… Кажется очень нечистым, даже если в конце концов это не имеет большого значения. Либо так, либо чистота определяется NeverToOptimizePrematurely, а не AvoidExecutingCodeYouKnowToBeUseless. - person ; 31.05.2017
comment
@gaazkam: я отредактировал ответ, чтобы предоставить альтернативное решение, которое не страдает от проблемы громоподобного стада, о которой вы говорите. - person caf; 31.05.2017