Кооперативная / не упреждающая многопоточность, позволяющая избежать взаимоблокировок? - PullRequest
2 голосов
/ 26 марта 2010

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

Некоторый фон:

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

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

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

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

Ответы [ 2 ]

1 голос
/ 26 марта 2010

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

0 голосов
/ 30 марта 2010

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

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

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

С уважением, Wayne

...