Что будет, если не назвать урожай в клетчатке?
Как я понял из документации yield()
функция передает управление другому волокну. Что произойдет, если мы не будем называть yield в волокне в D? Это будет означать, что нить будет зависать?
Или я неправильно понимаю, что волокна работают внутри потоков и они работают внутри процесса? И процесс может иметь или threads
или же fibers
?
2 ответа
Чтобы ответить на этот вопрос, важно понять, как работают волокна. Когда вы звоните Fiber.call()
метод, текущий контекст выполнения (состояние регистра ЦП) выгружается в память и вместо этого загружается контекст выполнения для этого объекта волокна. Когда вы звоните Fiber.yield()
текущий контекст выполнения также сбрасывается, но управление передается тому, кто в последний раз вызывал текущее волокно. Это может быть как другой контекст волокна, так и контекст простого потока - он не должен знать, так как любой контекст выполнения полностью определяется дампированными данными, ему даже не нужно знать о волокне.
Когда функция волокна заканчивается, она просто возвращает управление последнему вызывающему абоненту, как если бы yield
позвони в самый конец. Основное отличие состоит в том, что, когда функция волокна заканчивается, соответствующий объект волокна переходит в состояние "прекращено" и при выходе из него всегда остается в состоянии "работа" (даже если технически больше нет необходимости). Это важно, потому что это только определенное поведение для сброса и повторного использования волокон в завершенном состоянии.
Распространенная ошибка - рассматривать волокна как своего рода задачи и ожидать семантики планирования. Дело не в том, что волокно само по себе является простым примитивом переключения контекста для реализации любой интеллектуальной системы задач на вершине, никогда не будет никакого планирования самостоятельно.
Пример кода, показывающий соответствующую семантику:
void main ( )
{
import core.thread, std.stdio;
Fiber fiber1, fiber2;
fiber1 = new Fiber({
fiber2.call();
Fiber.yield();
});
fiber2 = new Fiber({
Fiber.yield();
});
fiber1.call(); // switches to fiber1, which switches to fiber2
// which yield back to fiber1 and finally fiber1 yield back to main
assert (fiber1.state == Fiber.State.HOLD && fiber2.state == Fiber.State.HOLD);
fiber2.call(); // switches to fiber2 which reaches end of function
// and switches back to main upon exit
assert (fiber1.state == Fiber.State.HOLD && fiber2.state == Fiber.State.TERM);
fiber1.call(); // switches to fiber1 which also reaches end of function
// and switches back to main upon exist
assert (fiber1.state == Fiber.State.TERM && fiber2.state == Fiber.State.TERM);
}
Если ваша функция волокна никогда yield()
s, то он не является кооперативным, что означает, что как только выполнение входит в эту функцию, другие волокна не завершат свою работу.