Рабочие потоки, задания, которые имеют определенный «цвет», только одно задание каждого цвета должно быть запущено, какой примитив синхронизации мне нужен? - PullRequest
0 голосов
/ 08 января 2020

У меня N рабочих потоков и очередь заданий. Когда рабочий поток простаивает, он выбирает задание из очереди и запускает его. Пока все просто.

Однако у моей работы есть свойство, которое я назову «цветным». Два задания одного цвета никогда не должны выполняться одновременно.

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

Мой вопрос: какие примитивы синхронизации я следует использовать здесь. Я думал о группировании очереди по цветам, и я могу прикрепить мьютекс к каждой цветовой группе, но потом я застрял в том, как использовать эти мьютексы. (Реальная программа написана на OCaml с использованием pthreads, поэтому у нее есть доступ к обычным примитивам pthread и примитивам, построенным поверх pthreads).

Это звучит как довольно необычный случай, но это связано с реальной проблемой Я пишу бегун зависимостей (думаю: "сделать"). Он никогда не должен запускать два рецепта («задания») параллельно, если оба рецепта нацелены на один и тот же выходной файл («цвет»).

Ответы [ 2 ]

1 голос
/ 09 января 2020

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

Существует множество объектов синхронизации, которые можно использовать для защиты очереди и любых других общих объектов от скачек данных. Среди них выделяются мьютексы и семафоры, но есть и другие.

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

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

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

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

    а. Ожидать переменную условия .

    b. Когда поток возвращается из ожидания, go возвращается к (2).

  3. (Если управление достигает этой точки, то в очереди имеется соответствующая задача.) Исключите подходящую задачу , T , цвета C ( T ).

  4. Обновите данные отслеживания цвета, чтобы показать, что задача цвет C ( T ) запущен.
  5. Разблокировать мьютекс .
  6. Выполнить задачу T .
  7. Блокировка мьютекса .
  8. Обновление данных отслеживания цвета, чтобы показать, что больше нет цветовой задачи C ( T ) работает.
  9. Передача в переменную условия .
  10. Go обратно в (2).

Полагаю, вы захотите включить условие завершения, чтобы ваши потоки могли корректно завершаться. Это, вероятно, будет оценено как часть шага (2). Убедитесь, что после выхода из l oop потоки разблокируют мьютекс .

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

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

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

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

1 голос
/ 08 января 2020

Существует несколько «очевидных» решений.

  1. Вы можете иметь «красный» поток и «синий» поток, обслуживая отдельные «красные» и «синие» очереди. Поскольку вы никогда не хотите, чтобы выполнялось более одной «красной» работы, наличие пула потоков ничего вам не даст.

  2. Если по какой-то причине вы все еще хотите мультиплексировать, «красная» "заданий в пуле потоков, вы все равно можете использовать отдельные" красные "и" синие "очереди и логический флаг, указывающий, выполняется ли соответствующее задание цвета. Затем свободный поток будет перебирать все непустые очереди и выбирать первую, которая имеет in_progress == false.

  3. . Вы можете объединить одну очередь с набором логических флагов. Теперь свободный поток будет перебирать очередь, пока не найдет работу, для которой in_progress[color] == false, и выберет ее.

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