Является ли delay () в Kotlin Coroutine неблокирующей функцией?

Комментарий в примере кода говорит, что delay () не блокирует. Должен ли он быть приостановлен?

https://kotlinlang.org/docs/reference/coroutines/basics.html

fun main() {
    GlobalScope.launch { // launch new coroutine in background and continue
        delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
        println("World!") // print after delay
    }
    println("Hello,") // main thread continues while coroutine is delayed
    Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}

person user1443721    schedule 24.03.2019    source источник
comment
Это правильное описание, потому что оно не блокирует какой-либо поток, а просто приостанавливает выполнение текущей сопрограммы.   -  person Moira    schedule 24.03.2019
comment
неблокирование - это хорошо определенный термин в компьютерных науках. Println (World!) Будет запущен немедленно, вместо ожидания 1 секунды, в зависимости от определения. Не используйте этот термин, если вы имеете в виду другое.   -  person user1443721    schedule 25.03.2019
comment
Мой смысл определенно не отличается, я не понимаю, что вы пытаетесь сказать. Как я только что объяснил, задержка - это не блокирующий вызов.   -  person Moira    schedule 25.03.2019
comment
@Moira: задержка приостанавливается и не блокируется. Джоффри ответил на это. это не только неблокирование.   -  person user1443721    schedule 26.03.2019
comment
@Moira: как вы сказали, он просто приостанавливает текущую сопрограмму. Почему в комментарии к вызову с задержкой этого не сказано? Вместо этого комментарий неблокирующий. Разве это не вводит в заблуждение?   -  person user1443721    schedule 26.03.2019
comment
Нет. Вы должны понимать, что сопрограммы - это, по сути, прославленные обратные вызовы (и компилируются как таковые). Обратный вызов, запланированный на 2000 мс, не блокирует ни один поток, в отличие, например, от Thread.sleep (поэтому он не блокирует), он просто приостанавливает сопрограмма. Выполнение текущей сопрограммы приостанавливается до тех пор, пока не будет достигнута точка приостановки. Сопрограммы - это не то же самое, что потоки, и документация должным образом не рассматривает их как таковые, даже если конечный результат аналогичен.   -  person Moira    schedule 26.03.2019
comment
приостановка и блокировка - это разные вещи.   -  person Killer    schedule 05.05.2020


Ответы (1)


delay приостанавливает и не блокирует.

TL; DR: delay действительно имеет эффект ожидания перед выполнением оператора, следующего за ним в текущей сопрограмме. Неблокирование просто означает, что во время этого ожидания текущий поток может делать что-то еще.


В документации Kotlin часто говорится о неблокировании для приостановки функций, чтобы было ясно, что они не блокируют текущий поток, а вместо этого просто приостанавливают текущую сопрограмму.

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

Тот факт, что они приостанавливают текущую сопрограмму, делает эти функции синхронными с точки зрения текущей сопрограммы, потому что сопрограмме необходимо дождаться завершения этих функций перед выполнением остальной части кода. Однако они фактически не блокируют текущий поток, потому что их реализация использует скрытые асинхронные механизмы.

person Joffrey    schedule 24.03.2019
comment
Спасибо! Ваш ответ разумный. неблокирование здесь действительно вводит в заблуждение. В формальном документе не следует использовать этот четко определенный термин для чего-то еще. Coroutine - это новая функция. Для объяснения функций стоит определить новый набор терминов. - person user1443721; 25.03.2019
comment
@ user1443721 FWIW эта терминология вообще не нова для асинхронного программирования; см. документы C # для пример. - person Moira; 25.03.2019
comment
@ user1443721 Именно это и сделал Котильн. Новая терминология приостанавливается, в то время как старая терминология (блокировка) сохраняет старое значение и по-прежнему относится к потокам. - person Marko Topolnik; 25.03.2019
comment
@Moira: неблокирование было четко определено даже раньше, чем C #. проверьте ответ на этот вопрос, stackoverflow.com/questions/10570246/ - person user1443721; 26.03.2019
comment
@Marko Topolnik: приостановка - не новая терминология. Он использовался для описания жизненного цикла потока. Мой вопрос в основном касается комментария к функции delay () в примере. - person user1443721; 26.03.2019
comment
@ user1443721 это именно моя точка зрения. Неблокирование используется давно (особенно в контексте асинхронных операций). - person Moira; 26.03.2019
comment
@ user1443721 Внутри JVM приостановка использовалась для метода Thread.suspend(), который никогда не реализовывался и не рекомендуется использовать уже 20 лет. Я думаю, вы сможете привыкнуть к его значению применительно к сопрограммам, не путать его с несуществующей приостановкой потока. Ни я, ни кто-либо из тех, кого я видел, писали об этом, не вызывали озабоченности по поводу двусмысленности. Кроме того, в каждом языке / среде используются одни и те же термины с немного разными значениями, это хорошо известное явление. Придумывать новые слова в каждой среде - не обычная практика. - person Marko Topolnik; 26.03.2019
comment
@Marko Topolnik: Вы признаете, что термин неоднозначен. Лучше написать более четкий комментарий, чтобы читателям было легче понять? Пример - Ваша первая сопрограмма в базовой категории. Это означает, что читатели - новички в сопрограммах. - person user1443721; 26.03.2019
comment
@Moira: но вы должны понимать, что неблокирование не означает приостановки. Вот в чем суть. - person user1443721; 26.03.2019
comment
@ user1443721 Вы правы, но эта функция является функцией приостановки, поэтому я предполагаю, что это будет лишним. Я не писал документацию, но полагаю, что это, в сочетании с тем фактом, что результат задержки вызова в некоторой степени очевиден, привело к тому, что это не было упомянуто в документации. - person Moira; 26.03.2019
comment
@Moira: Опять же, это ваша первая сопрограмма. Читатель не знает, что такое delay (). - person user1443721; 26.03.2019
comment
@Marko Topolnik: Необязательно иметь Thread.suspend (). Заблокированный поток находится в состоянии приостановки. В Java есть еще один метод yield (), который также может отправить поток для приостановки. - person user1443721; 26.03.2019
comment
@ user1443721 Я думаю, что сейчас вы говорите о приостановке задач на уровне вытесняющей многозадачности ОС, поэтому вы используете совершенно другую систему координат. Однако, когда ОС вытесняет собственный поток, выполняющий данный поток Java, состояние потока Java остается RUNNABLE. - person Marko Topolnik; 26.03.2019
comment
если Dispatchers.Main используется для запуска сопрограммы с использованием launch (Dispatchers.Main) {delay (1000)}, выполняется ли задержка в основном потоке или в каком-то фоновом потоке? - person Hari Kiran; 24.07.2020
comment
@HariKiran Я думаю, можно сказать, что delay() никуда не денется. Сопрограмма, запущенная launch, выполняется в основном потоке, затем достигает delay(), который приостанавливает эту сопрограмму. Это означает, что основной поток может выполнить какой-то другой код, ожидая завершения этой задержки, а затем запущенная сопрограмма может возобновить выполнение кода после delay() в основном потоке. Я считаю, что ожидание и момент возобновления сопрограммы обрабатываются самим диспетчером, но я не знаю его внутренних особенностей. - person Joffrey; 19.02.2021