Хорошее значение манипулирования потоком - PullRequest
2 голосов
/ 12 мая 2011

Я написал простую программу, которая реализует схему мастер / рабочий, где мастер является основным потоком, а рабочие создаются им.

Основной поток записывает что-то в общий буфер, а рабочие потоки читают этот общий буфер, запись и чтение в общий буфер организуются с помощью блокировки чтения / записи.

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

Согласно отличному сообщению , посвященному аналогичной проблеме, я обнаружил, что, вероятно, недопустимо манипулировать приоритетом потока в политике SCHED_OTHER, что можно изменить только значением nice.

Я написал процедуру, чтобы дать рабочим потокам более низкий приоритет, чем основному потоку, но, похоже, он работает неправильно.

void assignWorkerThreadPriority(pthread_t* worker)
{
    struct sched_param* worker_sched_param = (struct sched_param*)malloc(sizeof(struct sched_param));
    worker_sched_param->sched_priority =0; //any value other than 0 gives error?
    int policy = SCHED_OTHER;
    pthread_setschedparam(*worker, policy, worker_sched_param);
    printf("Result of changing priority is: %d - %s\n", errno, strerror(errno));
}

У меня двоякий вопрос:

  1. Как установить приятное значение рабочих потоков, чтобы избежать истощения основного потока.
  2. Если это невозможно, то как я могу изменить политику планирования на такую, которая позволяет изменять приоритет.

Редактировать: мне удалось запустить программу с использованием других политик, таких как SCHED_FIFO, все, что мне нужно было сделать, это запустить программу как суперпользователь

1 Ответ

1 голос
/ 12 мая 2011

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

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

  • Запись потока:
    • Создание рабочего элемента.
    • Блокировка мьютекса или CriticalSectionзащита текущей очереди и указатель на очередь.
    • Добавить рабочий элемент в очередь.
    • Снять блокировку.
    • При желании сигнализировать переменную условия или событие.Другой вариант - для рабочих потоков проверить работу на таймере.
  • Рабочий поток:
    • Создать новую очередь.
    • Ожидать условиепеременная, событие или другой сигнал, или ожидание по таймеру.
    • Блокировка мьютекса или CriticalSection, защищающих текущую очередь и указатель на очередь.
    • Установка указателя текущей очереди на новую очередь.
    • Снять блокировку.
    • Приступить к работе с теперь закрытой очередью.
    • Удалить очередь после завершения всех рабочих элементов.
  • Теперь запись потока создает больше рабочих элементов.Когда все рабочие потоки имеют свои собственные копии очереди для работы, она сможет спокойно писать множество элементов.

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

...