Re[12]: Можно ли избавиться от async|await?
От: Shmj Ниоткуда  
Дата: 16.12.25 10:14
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Нет конечно, time.Sleep создает под капотом таймер, который при срабатывании вызывает continuation у горутины. В зависимости от того, в каком порядке сработали эти таймеры, получится разный порядок цифр.


Чем это лучше запуска в ThreadPool — и через ThreadPool и через go — нельзя простым образом получить результат.

А то что все функции в go асинхронные — вы не доказали. Жду доказательство.
=сначала спроси у GPT=
Re[12]: Можно ли избавиться от async|await?
От: Shmj Ниоткуда  
Дата: 16.12.25 10:15
Оценка:
Здравствуйте, wl., Вы писали:

S>>В потоке (для каждого go создается свой поток), вот доказательство: https://go.dev/play/p/oDoPGmB7QU1

wl.>если выводит ThreadId, он всегда одинаковый: https://go.dev/play/p/EbNWMIwOBqN

А обманывать то зачем:

--- 2. Ожидание выполнения ---
Thread ID: 13
Thread ID: 13
Thread ID: 13
Thread ID: 15
Thread ID: 11
Thread ID: 13
Thread ID: 11
Thread ID: 11
Thread ID: 14
Thread ID: 13


— разный. Видимо запуск в пуле потоков. Чем ваше go отличается от запуска в ThreadPool?
=сначала спроси у GPT=
Re[11]: Можно ли избавиться от async|await?
От: mrTwister Россия  
Дата: 16.12.25 10:22
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, mrTwister, Вы писали:


S>Как ты это сможешь доказать? Ок, c go — асинхронный, верю. А без go — какие ваши доказательства что оно асинхрон?


T>>и несмотря на запуск 10 тасок/10 горутин, будет по факту использовано скорее не 10 потоков, а меньше.


S>Так это и в C# — там ThreadPool.


Я это и написал

T>>Таким образом оба варианта можно, например, безопасно вызывать в http хендлере не опасаясь заблокировать работу http сервера из-за thread pool depletion


S>Это не доказательство — завимсит от реализации обработки http.


Современный http сервер на .net поддерживает асинхронность

S>Давай доказательство на твоем коде.

Запусти его с GOMAXPROCS=1, в этом случае все выполнится строго в одном потоке

S>Это вы реализовали функционал async|await, но весьма криво — через каналы. Это раньше приводил вам.

В чем кривость?
лэт ми спик фром май харт
Re[12]: Можно ли избавиться от async|await?
От: Shmj Ниоткуда  
Дата: 16.12.25 10:25
Оценка:
Здравствуйте, mrTwister, Вы писали:

S>>Давай доказательство на твоем коде.

T>Запусти его с GOMAXPROCS=1, в этом случае все выполнится строго в одном потоке

Вопрос такой: я убедился что go запускает в пулле потоков. А как мне убедиться что без go тоже выполняется асинхронно а не обычным синхронным образом?
=сначала спроси у GPT=
Re[13]: Можно ли избавиться от async|await?
От: mrTwister Россия  
Дата: 16.12.25 10:31
Оценка:
Здравствуйте, Shmj, Вы писали:


S>А обманывать то зачем:

У меня тоже первый раз в одном отработало, тут race condition

S>

S>--- 2. Ожидание выполнения ---
S>Thread ID: 13
S>Thread ID: 13
S>Thread ID: 13
S>Thread ID: 15
S>Thread ID: 11
S>Thread ID: 13
S>Thread ID: 11
S>Thread ID: 11
S>Thread ID: 14
S>Thread ID: 13


S>- разный. Видимо запуск в пуле потоков.


Даже тут у тебя идентификаторы потоков повторяются, а значит для каждой горутины не создается отдельный поток

S>Чем ваше go отличается от запуска в ThreadPool?


Тем, что в go горутина не может заблокировать поток, благодаря этому thread pool в go фиксированного размера, по умолчанию в нем число потоков равно числу ядер и новые потоки не добавляются, потому что это не надо. Благодаря этому в го нельзя заблокировать асинхронный контекст и избежать проблем: https://rsdn.org/forum/flame.comp/9030348.1
Автор: mrTwister
Дата: 15.12 00:13

В go ты можешь иметь в тредпуле 1 поток и запустить 100000 конкурентных горутин, которые будут выполняться "одновременно" на этом единственном потоке. Если ты в C# запустишь 100000 Task.Run(async () => while(true) {}), то у тебя все встанет раком. А в go горутины будут одновременно работать как ни в чем не бывало на одном единственном потоке.
лэт ми спик фром май харт
Re[13]: Можно ли избавиться от async|await?
От: mrTwister Россия  
Дата: 16.12.25 10:32
Оценка:
Здравствуйте, Shmj, Вы писали:

T>>Запусти его с GOMAXPROCS=1, в этом случае все выполнится строго в одном потоке


S>Вопрос такой: я убедился что go запускает в пулле потоков. А как мне убедиться что без go тоже выполняется асинхронно а не обычным синхронным образом?


Я же написал: запусти его с GOMAXPROCS=1
лэт ми спик фром май харт
Re[13]: Можно ли избавиться от async|await?
От: mrTwister Россия  
Дата: 16.12.25 10:38
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, mrTwister, Вы писали:


T>>Нет конечно, time.Sleep создает под капотом таймер, который при срабатывании вызывает continuation у горутины. В зависимости от того, в каком порядке сработали эти таймеры, получится разный порядок цифр.


S>Чем это лучше запуска в ThreadPool — и через ThreadPool и через go — нельзя простым образом получить результат.


Тем, что во время ожидания не блокируется поток. Ты же почему-то написал "await Task.Delay(...)", а не "Thread.Sleep(...)", почему?

S>А то что все функции в go асинхронные — вы не доказали. Жду доказательство.


Как ты объяснишь, что ThreadID у горутин повторялся, несмотря на то, что они работали одновременно (висели в time.Sleep)?
лэт ми спик фром май харт
Re[14]: Можно ли избавиться от async|await?
От: Shmj Ниоткуда  
Дата: 16.12.25 11:11
Оценка:
Здравствуйте, mrTwister, Вы писали:

S>>Вопрос такой: я убедился что go запускает в пулле потоков. А как мне убедиться что без go тоже выполняется асинхронно а не обычным синхронным образом?

T>Я же написал: запусти его с GOMAXPROCS=1

И что должно быть?
=сначала спроси у GPT=
Re[15]: Можно ли избавиться от async|await?
От: mrTwister Россия  
Дата: 16.12.25 11:20
Оценка: -1
Здравствуйте, Shmj, Вы писали:

T>>Я же написал: запусти его с GOMAXPROCS=1


S>И что должно быть?


Всегда будет один ThreadID, при том, что запущенные функции работают одновременно. Это возможно только если выполняемые в горутинах функции асинхронны.
лэт ми спик фром май харт
Re[16]: Можно ли избавиться от async|await?
От: Shmj Ниоткуда  
Дата: 16.12.25 11:27
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Всегда будет один ThreadID, при том, что запущенные функции работают одновременно. Это возможно только если выполняемые в горутинах функции асинхронны.


Т.е. при вызове через go. А как убедиться что асинхрон и без вызова через go?
=сначала спроси у GPT=
Re[14]: Можно ли избавиться от async|await?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.12.25 11:32
Оценка:
Здравствуйте, mrTwister, Вы писали:


T>В go ты можешь иметь в тредпуле 1 поток и запустить 100000 конкурентных горутин, которые будут выполняться "одновременно" на этом единственном потоке. Если ты в C# запустишь 100000 Task.Run(async () => while(true) {}), то у тебя все встанет раком. А в go горутины будут одновременно работать как ни в чем не бывало на одном единственном потоке.


.Net Использует пул потоков. Для долгих задач есть опция LongRunning

Асинхронное программирование на основе задач

Ну и можно регулировать планировщиками

Task изнутри: управление потоками в .NET и создание своих планировщико
и солнце б утром не вставало, когда бы не было меня
Re[17]: Можно ли избавиться от async|await?
От: mrTwister Россия  
Дата: 16.12.25 11:53
Оценка: 1 (1)
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, mrTwister, Вы писали:


T>>Всегда будет один ThreadID, при том, что запущенные функции работают одновременно. Это возможно только если выполняемые в горутинах функции асинхронны.


S>Т.е. при вызове через go. А как убедиться что асинхрон и без вызова через go?


Ну вот пример: https://go.dev/play/p/1fVjMvIaGmq
package main

import (
    "syscall"
    "time"
)

func Foo() {
    println("Foo started at thead #", syscall.Gettid())
    time.Sleep(time.Millisecond * 100)
    println("Foo finished at thead #", syscall.Gettid())
}

func main() {
    for range 10 {
        go func() {
            time.Sleep(time.Millisecond * 100)
        }()
    }
    Foo()
}

Я функцию Foo запускаю без всяких горутин, а просто "Foo()".
Программа вывела:
Foo started at thead # 11
Foo finished at thead # 14


То есть функция начала работать на одном потоке ОС, а закончила на другом потоке. Как это возможно, если бы она не была асинхронной?
Параллельно я запустил еще десяток горутин без функции Foo, чтобы переезд на тругой тред чаще воспроизводился. Оно воспроизводится и без этого, но не каждый раз, надо просто чаще позапускать (иногда раз 10): https://go.dev/play/p/087bV3w7fMT

  Скриншот
лэт ми спик фром май харт
Отредактировано 16.12.2025 11:54 mrTwister . Предыдущая версия .
Re[15]: Можно ли избавиться от async|await?
От: mrTwister Россия  
Дата: 16.12.25 12:50
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>.Net Использует пул потоков. Для долгих задач есть опция LongRunning


Я в курсе. Проблемы подхода .net описывал тут:
https://rsdn.org/forum/flame.comp/9030348.1
Автор: mrTwister
Дата: 15.12 00:13

https://rsdn.org/forum/flame.comp/9029848.1
Автор: mrTwister
Дата: 13.12 21:17
лэт ми спик фром май харт
Re[16]: Можно ли избавиться от async|await?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.12.25 14:00
Оценка:
Здравствуйте, mrTwister, Вы писали:

S>>.Net Использует пул потоков. Для долгих задач есть опция LongRunning


T>Я в курсе. Проблемы подхода .net описывал тут:

T>https://rsdn.org/forum/flame.comp/9030348.1
Автор: mrTwister
Дата: 15.12 00:13

T>https://rsdn.org/forum/flame.comp/9029848.1
Автор: mrTwister
Дата: 13.12 21:17


Угу решение все асинхронные операции выполнять в одном потоке не есть правильное решение или все сводить к функциональщине на иммутабельных объектах.
На C# можешь делать все на одном потоке со своим планировщиком.

LongRunning не зря придуман. Для оптимального программирования нужны различные инструменты.
и солнце б утром не вставало, когда бы не было меня
Re[18]: Можно ли избавиться от async|await?
От: · Великобритания  
Дата: 16.12.25 14:42
Оценка: +1
Здравствуйте, 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 — совсем красиво будет.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[19]: Можно ли избавиться от async|await?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.12.25 15:31
Оценка:
Здравствуйте, ·, Вы писали:


·>val1 := func1() // "асинхронный" вызов 1 (на самом деле, конечно же нет)

·>val2 := func2() // "асинхронный" вызов 2 (на самом деле, конечно же нет)

C# это Task.WhenAll
и солнце б утром не вставало, когда бы не было меня
Re[20]: Можно ли избавиться от async|await?
От: · Великобритания  
Дата: 16.12.25 15:42
Оценка: +2
Здравствуйте, Serginio1, Вы писали:

S>·>val1 := func1() // "асинхронный" вызов 1 (на самом деле, конечно же нет)

S>·>val2 := func2() // "асинхронный" вызов 2 (на самом деле, конечно же нет)
S> C# это Task.WhenAll
Зачем ты это мне рассказываешь, да ещё и фигню невтемную говоришь? В данном случае будет как-то так:
var r1 = func1();
var r2 = func2();
System.Console.WriteLine(await(r1) + await(r2));

И эти функции ДОЛЖНЫ быть объявлены как async и быть написаны правильно на всю глубину вызовов, протаскивая async повсюду. Сабж!
Это же полная Ж по сравнению с java.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[19]: Можно ли избавиться от async|await?
От: mrTwister Россия  
Дата: 16.12.25 15:51
Оценка:
Здравствуйте, ·, Вы писали:

·>Здравствуйте, 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
}

func main() {
    val1 := RunTask(func1)
    val2 := RunTask(func2)
    println(val1.Get() + val2.Get())
}

// повторно используемый хелпер
type Task[Result any] chan Result

func (t Task[Result]) Get() Result {
    return <-t
}

func RunTask[Result any](f func() Result) Task[Result] {
    res := make(chan Result)
    go func() { res <- f() }()
    return res
}
лэт ми спик фром май харт
Re[21]: Можно ли избавиться от async|await?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.12.25 16:40
Оценка:
Здравствуйте, ·, Вы писали:


S>>·>val1 := func1() // "асинхронный" вызов 1 (на самом деле, конечно же нет)

S>>·>val2 := func2() // "асинхронный" вызов 2 (на самом деле, конечно же нет)
S>> C# это Task.WhenAll
·>Зачем ты это мне рассказываешь, да ещё и фигню невтемную говоришь? В данном случае будет как-то так:
·>
·>var r1 = func1();
·>var r2 = func2();
·>System.Console.WriteLine(r1) await(+ await(r2));
·>

·>И эти функции ДОЛЖНЫ быть объявлены как async и быть написаны правильно на всю глубину вызовов, протаскивая async повсюду. Сабж!
·>Это же полная Ж по сравнению с java.

Ну и чем это лучше
Task.WhenAll
await Task.WhenAll(r1,r2);
System.Console.WriteLine(r1.Result+r2.Result);


или

var res = await Task.WhenAll(r1,r2);
System.Console.WriteLine(res[0]+res[1]);


А если мне нужно выполнение первой функции?
Чередование

Часто нужно сделать TimeOut

int timeout = 1000;
var task = SomeOperationAsync();
if (await Task.WhenAny(task, Task.Delay(timeout)) == task) {
    // task completed within timeout
} else { 
    // timeout logic
}
и солнце б утром не вставало, когда бы не было меня
Отредактировано 16.12.2025 16:44 Serginio1 . Предыдущая версия .
Re[20]: Можно ли избавиться от async|await?
От: novitk США  
Дата: 16.12.25 17:00
Оценка:
Здравствуйте, mrTwister, Вы писали:

T>Делается тривиальный хелпер на три строчки и код будет выглядеть точно так же

И в результате имеем ровно тоже, что и в .net , но там в отличие от GoLang не забыли про ошибки и как и положено сделали каналы опциональными.
Пальцы устали уже писать, что в GoLang нет бесшовной ассинхронности, а вот в Project Loom она таки есть — одну и туже функцию можно запустить и так и этак.
Отредактировано 16.12.2025 17:22 novitk . Предыдущая версия . Еще …
Отредактировано 16.12.2025 17:19 novitk . Предыдущая версия .
Отредактировано 16.12.2025 17:19 novitk . Предыдущая версия .
Отредактировано 16.12.2025 17:11 novitk . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.