Реализация приоритетной очереди с переменной условия в C

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

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

Спасибо!


person David M    schedule 07.11.2009    source источник


Ответы (3)


Я думаю, вам следует переосмыслить то, что вы пытаетесь сделать. Если вы пытаетесь оптимизировать свою производительность, вы, вероятно, ошибаетесь.

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

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

Кроме того, что произойдет, если поток с более высоким приоритетом начнет ожидать условную переменную в тот же момент, когда эта условная переменная получает сигнал? Кто разблокируется, вновь прибывший поток с высоким приоритетом или прежний поток с наивысшим приоритетом?

Порядок, в котором потоки разблокируются, полностью зависит от планировщика потоков ядра, так что вы в его власти. Я бы даже не стал предполагать порядок FIFO.

person Adam Rosenfield    schedule 07.11.2009

Поскольку условные переменные в основном являются просто барьером, и вы не можете контролировать очередь ожидающих потоков, нет реального способа применить приоритеты. Неверно предполагать, что ожидающие потоки будут действовать в порядке FIFO.

С помощью комбинации атомарных переменных, дополнительных условных переменных и предварительного знания вовлеченных потоков/приоритетов вы могли бы создать решение, в котором сигнальный поток будет повторно сигнализировать главному CV, а затем повторно блокировать CV с приоритетом, но это, конечно, не будет t быть общим решением. Это также не в моей голове, так что может быть и другой недостаток.

person Andrew Grant    schedule 07.11.2009

Именно планировщик определяет, какой поток будет запущен. Вы можете посмотреть pthread_setschedparam и pthread_getschedparam и поиграйтесь с политиками (SCHED_OTHER, SCHED_FIFO или SCHED_RR) и приоритетами. Но, вероятно, это не приведет вас туда, куда, как я подозреваю, вы хотите попасть.

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

person Duck    schedule 07.11.2009