Совместная / не упреждающая обработка потоков, позволяющая избежать взаимоблокировок?

StackOverflow https://stackoverflow.com/questions/2521527

Вопрос

Есть какие-нибудь творческие идеи, чтобы избежать взаимоблокировок при выходе или перейти в режим ожидания с совместной / не упреждающей многозадачностью без выполнения потока O / S.Перейти в режим ожидания (10)?Обычно вызов yield или sleep возвращает запрос в планировщик для выполнения других задач.Но иногда это может привести к тупиковым ситуациям.

Некоторая предыстория:

Этому приложению очень нужна скорость, и на данный момент оно чрезвычайно быстрое по сравнению с другими системами в той же отрасли.Одним из методов повышения скорости является совместное / непередавающее потокование, а не стоимость переключения контекста из потоков O / S.

На высоком уровне разрабатывается менеджер приоритетов, который вызывает задачи в зависимости от приоритета и времени обработки.Каждая задача выполняет одну "итерацию" работы и возвращается, чтобы снова дождаться своей очереди в очереди приоритетов.

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

В этом случае у нас есть 3 задачи, A B и C, где A - контроллер, который должен синхронизировать активность B и C.Во-первых, A запускает как B, так и C.Затем B выдает результат, так что вызывается C.Когда C уступает, A видит, что они оба неактивны, и решает, что B пора запускать, но для C пока нет времени.Ну, а B теперь застрял в yield, который вызвал C, так что он никогда не сможет запуститься.

Это было полезно?

Решение 2

Что ж, понял, что идеальным решением для этого было бы, если бы язык C # поддерживал истинные "продолжения", чтобы расширить стек и продолжить с того места, где остановились позже.

В отсутствие этого мы делаем нашу собственную импровизированную замену, разрешая задачам в этой ситуации устанавливать флаг "isInterrupted" равным true и возвращать - тем самым разматывая stack.

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

С уважением,, Уэйн

Другие советы

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top