Здравствуйте, mrTwister, Вы писали:
T>То есть функция начала работать на одном потоке ОС, а закончила на другом потоке. Как это возможно, если бы она не была асинхронной?
Простите, но это уличная магия, а не асинхронность. Так работает шедулер и переключение контекста. После thread park (то что делает sleep) шедулер может продолжить исполнение на другом ядре. Это многопоточность, а не асинхронность.
Асинхронный это если части кода выполняются одновременно. Примерно так, код, ясен пень, неработающий:
func func1() int {
// какой-нибудь сетевой вызов, который длится 3 секунды
time.Sleep(3 * time.Second)
return 1;
}
func func2() int {
// какой-нибудь сетевой вызов, который длится 5 секунд
time.Sleep(5 * time.Second)
return 2;
}
val1 := func1() // "асинхронный" вызов 1 (на самом деле, конечно же нет)
val2 := func2() // "асинхронный" вызов 2 (на самом деле, конечно же нет)
fmt.Println(val1 + val2) // используем результаты и комбинируем
// вот это всё должно отработать за 5 секунд, а не за 8.
Именно для такого придумали async/await. Но выглядит отстойно и прошлый век. Собственно поэтому и сабж.
Впрочем, в гошке такое будет ещё хуже, особенно если озаботиться обработкой ошибок.
Самый вменяемый код — это на Java:
int func1() throws Exception {
SECONDS.sleep(3);
return 1;
}
int func2() throws Exception {
SECONDS.sleep(5);
return 2;
}
void main() throws Exception {
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
var r1 = executor.submit(() -> func1());
var r2 = executor.submit(() -> func2());
System.out.println(r1.get() + r2.get());
}
}
тут можно поиграться.
Вдобавок ещё пилят
https://openjdk.org/jeps/525 — совсем красиво будет.