Здравствуйте, Serginio1, Вы писали:
N>>И что? ОС всё равно должна будет сделать это рано или поздно, если задача сама не отдаёт управление. А если отдаёт, то зачем ОС принудительно переключать?
S>То что желательно указать в какие моменты можно переключать. Например дождаться выполнения lock
Эээ... после выполнения захвата лока (речь об этом, да?) как раз лучше не отдавать управление, а сделать максимум действий во время захвата. А до него — если лок занят — то раз ждём, надо оповестить шедулер о том, что есть отличный повод запустить другую задачу.
N>>Нет, само по себе ничего из цитированного не является тут аргументом в сторону async/await. Там точно так же — если управление отдано явно, то шедулер не будет забирать насильно, а если нет, то заберёт — скорее всего, средствами ОС. Более того, если в момент переключения на входе или выходе await не будет явно сказано "а теперь подумайте, не переключить ли" соответствующим системным вызовом, то ОС не будет знать, когда там userland занимается переключением вокруг awaitʼа, и тоже переключит в непредсказуемый (и, возможно, неподходящий) момент.
S> Ну как же не. Как раз проблема в большей степени это проблемы с Синхронизирующие примитивы ядра. Мьютексы, Семафоры, эвенты и т. д.
И в чём тут проблема?
S>Для примера в эпоху до async/await поток ждет выполнения асинхронной операции.
S>async/await берет на себя сохранения данных внутри класса (стек не нужен) и строит автомат и тот же поток который выполнял данную задачу, запускает другую. Нет никаких переключений.
А что, вот эти все "берёт на себя сохранения данных внутри класса" и аналогичное восстановление, по-вашему, не переключение? А что оно такое тогда?
S> Не зря же используют SpinLock. Если бы стоимость переключения была не важна, то нафига он нужен?
Вот
этот, да?
Действительно, стоимость переключения (любого — в том числе которого вы не замечаете цитатой выше) высока. Но при чём тут спинлоки?
Спинлок это очень специфичное средство, которое становится эффективным только при одновременном выполнении двух условий: 1) конкуренты за лок чаще находятся на разных физических исполнителях (железных тредах, harts) и 2) длительность возможной конкуренции относительно мала. Иначе трата процессора на кручение вокруг ячейки памяти в ожидании, пока в той появится заветный нолик, слишком велика — лучше таки переключиться.
Классический мьютекс ещё со времён Solaris поэтому делает N попыток захвата как спинлока (процессорной операцией типа CAS, LL/SC), а если не получилось — уходит в ядерный вызов. В Linux сделано (в futex) так же. Что в Windows, не знаю, облом докапываться до исходников. Но использовать SpinLock как аргумент в пользу дороговизны переключения — это, мягко говоря, странно.
S>Зачем тогда async/await
С точки зрения логики управления выполнением — именно для тех случаев, когда шедулер узнал, что ответа для await сейчас нет и надо дать кому-то управление.
С точки зрения исходного кода — чтобы писать его максимально линейно.
Переключений в нём, в идеале, столько же, сколько в аналогичном коде на коллбэках или промисах.
S>Ну и замена всяких Lock на ManualResetValueTaskSource
S>http://rsdn.org/forum/dotnet/8030645.1Автор: Serginio1
Дата: 16.06.21
S> https://stackoverflow.com/questions/66387225/awaiting-a-single-net-event-with-a-valuetask
Я что-то не могу это раскурить. Какой смысл в его применении?
S>Конечно зависит от длительности задач, но если задачи непродолжительные, то пул потоков может и не переключаться а выполнять очередь заданий.
Тоже не понимаю, при чём тут эта реплика.