Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Shallow Dip into Kotlin Coroutine
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
bigbackboom
April 17, 2024
Technology
290
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Shallow Dip into Kotlin Coroutine
bigbackboom
April 17, 2024
More Decks by bigbackboom
See All by bigbackboom
Learn as a Pair
bigbackboom
0
87
Not 2 L8 JKでもわかるMaterial 3
bigbackboom
0
79
JKでもわかるSFace Recognition
bigbackboom
0
99
Androidタブレットアプリ作成_棚から牡丹餅を得るにはまず棚から
bigbackboom
0
78
Proto Datastoreを使う前の心構え
bigbackboom
0
380
Extended A Study in Bitmap: Is NDK the fast Processing method by CPU?
bigbackboom
0
52
Have A Dog in CircleCI
bigbackboom
0
120
Androidエンジニアのお仕事でのショボーン
bigbackboom
0
110
解明!楽しいプレゼンする話すスキル
bigbackboom
0
150
Other Decks in Technology
See All in Technology
新卒エンジニア、 介護士になる
ryu1013
1
690
TSKaigi Sendai 2026 - tsgo時代のTypeScript Playgroundはどう動くか
teamlab
PRO
0
110
cdkd (CDK Direct)
gotok365
4
270
Flutter Widget Previewerで始めるUIプレビューとVRTの自動化
sakusaku3939
0
210
re:Invent2026 事前勉強会 歴史と愉しみ方10分LT編
toshi_atsumi
0
150
登壇はいいぞ! 〜Kaigi on Railsに登壇して起きた3つの変化〜
occhi
0
110
「いつか使う」の「いつか」は来ない 〜AI駆動開発における「作らない」判断について〜
ikki0006
0
150
なぜ東京にいる私が、新潟の技術コミュニティを運営するのか by 八雲慎之助
yakumo
0
220
サボる子はいねぇがー!AgentCoreハーネスの脆弱性に学ぶ、エージェントの入力バリデーション
iwamot
PRO
5
300
Deep Data Security 機能解説
oracle4engineer
PRO
3
1k
Autonomous AI Lakehouse - Live AI Hubから始めるセキュアなAIデータ活用 -
oracle4engineer
PRO
3
200
デザインレビューは自動化できるのか?─ Flutter × Figma で UI 品質保証を考える
techiro
2
820
Featured
See All Featured
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
2
430
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.4k
The Curse of the Amulet
leimatthew05
3
17k
Amusing Abliteration
ianozsvald
1
380
The Mindset for Success: Future Career Progression
greggifford
PRO
0
560
Designing for Timeless Needs
cassininazir
1
550
Visualization
eitanlees
153
17k
Darren the Foodie - Storyboard
khoart
PRO
4
4.1k
[SF Ruby Conf 2025] Rails X
palkan
3
1.5k
The AI Search Optimization Roadmap by Aleyda Solis
aleyda
2
6.4k
Statistics for Hackers
jakevdp
799
230k
Into the Great Unknown - MozCon
thekraken
41
2.8k
Transcript
Shallow Dip into Kotlin Coroutine キクチコウダイ
自己紹介 菊池 広大(キクチコウダイ) 2023年6月 株式会社マネーフォワードに入社 埼玉出身、香港育ち、 Iターンで東京から福岡に引越し Github: https://github.com/BigBackBoom
発表の概要
Coroutineとは Coroutineが スレッドの並列処理とどう違うのか、 Kotlinをベースに説明します。
Coroutineとは
Coroutineとは サブルーチンを並列処理させるために 一般化した手法
Coroutineとは • もともとは1963年にCobolのコンパイラ周りで提唱された • 複数のサブルーチンが自分の処理を中断し、プロセス間で リソースの協力をしながら並列処理を実行する。
Coroutineとは
Coroutineとは 普通のサブルーチン(メソッド)とは違うの? a. サブルーチンは呼び出されるたびに、一から処理が開 始される b. Coroutineはサブルーチンで処理を中断して、別の処 理の開始・再開ができる
Coroutineとは スレッド使えば十分じゃない? • スレッドはOS管理されている。そのため、OS毎に実装 を変更・バイナリの再コンパイルする必要がある。 • また、スレッドを複数立ち上げると、ハードウェアリソー スも大量に消費する。
Kotlin Coroutineの使い方
Launch Lauchを呼び出すことでCoroutineの非同期 処理を開始できる fun main(args: Array<String>) { GlobalScope.launch { println("world")
} println("Hello") // 結果 // Hello } Launch
Launch • Launch処理が始まる前にmainが終 わってしまうので変更 • runBlockingは通常コードとCoroutine をブリッジするために使われる • Globalscopeを直接指定するのは、 Warningが出るので注意
fun main(args: Array<String>) { runBlocking { launch { println("Hello") } } println("World") // Hello // World } Launch
Launch • Coroutine内でサブルーチンを呼び出 す • サブルーチンの定義にsuspendをつけ る • サブルーチンの呼び出しで処理の中断 が行われる
suspend fun printWorld() { delay(1000) // 中断 println("world") } fun main(args: Array<String>) { runBlocking { launch { printWorld() // 中断 } println("Hello") } // Hello // 〜1秒休憩〜 // World } } Suspend
Coroutineの実現方法
Coroutineの実現方法 Coroutineの処理はコンパイル時に ステートマシンコードが生成され置き換えられる。 単純にメソッドが実行されるわけではない
ステートマシン 右のコードをJVMバイトコードからデコンパイ ルして、中身を確認しました suspend fun printWorld() { delay(1000) // 中断
println("world") } fun main(args: Array<String>) { runBlocking { launch { printWorld() // 中断 } println("Hello") // Hello // World }
ステートマシン デコンパイルした中身を擬似コード化 1. mainのLaunchの中身が実行される fun printWorld(continue: Continuation) { val cont
= ContinuationImpl() { fun invokeSuspend() { printWorld() } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
ステートマシン デコンパイルした中身を擬似コード化 1. mainのLaunchの中身が実行される 2. 非同期なので、Helloがコンソールに表 示 fun printWorld(continue: Continuation)
{ val cont = ContinuationImpl() { fun invokeSuspend() { printWorld(this) } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
ステートマシン 3. launchのlabelの0が実行され、 printWorldのメソッドが動く fun printWorld(continue: Continuation) { val cont
= ContinuationImpl() { fun invokeSuspend() { printWorld(this) } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
ステートマシン 3. launchのlabelの0が実行され、 printWorldのメソッドが動く 4. printWorldでDelayedが走り、 printWorldを再開先として、 ContinuationImplを渡す。 fun printWorld(continue:
Continuation) { val cont = ContinuationImpl() { fun invokeSuspend() { printWorld(this) } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
ステートマシン 3. launchのlabelの0が実行され、 printWorldのメソッドが動く 4. printWorldでDelayedが走り、 printWorldを再開先として、 ContinuationImplを渡す。 5. returnされて一旦全体の処理が終了す
る。 fun printWorld(continue: Continuation) { val cont = ContinuationImpl() { fun invokeSuspend() { printWorld(this) } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
ステートマシン 3. launchのlabelの0が実行され、 printWorldのメソッドが動く 4. printWorldでDelayedが走り、 printWorldを再開先として、 ContinuationImplを渡す。 5. returnされて一旦全体の処理が終了す
る。 6. 1秒経つと、ContinuationImplの invokeSuspendが実行され、再度 printWorldを実行。 fun printWorld(continue: Continuation) { val cont = ContinuationImpl() { fun invokeSuspend() { printWorld(this) } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
ステートマシン 7. 二度目では、ラベルがマイナスに更新さ れているため、Worldがコンソールに表 示 fun printWorld(continue: Continuation) { val
cont = ContinuationImpl() { fun invokeSuspend() { printWorld(this) } } switch(continue.label){ 0: label = 1 if(Delayed(1000, cont) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } println(“world") } // EventLoop // Default label = 0 fun main() { runBlocking { launch { switch(label){ 0: label = 1 if(printWorld(this) == suspend) return suspend break; 1: throwOnFailure 2: ThrowIllegalState } } println("Hello") } }
Coroutineの実現方法 中断の原理はステートマシンだったとして 並列処理はなんでできるの?
Coroutineの実現方法 Coroutineの実行周りは三つのクラスに分かれる • Job:launch, async, flowなどのたびに作成される。 • Worker:スレッドそのもの、Jobを実行する。 • Scheduler:Workerを管理する。リソース管理を行う
Coroutineの実現方法
Coroutineの実現方法 • 並列処理自体は、スレッドにて実現 • 一つのスレッドが複数の処理を実行するので、処理ご とにスレッドを立ち上げるよりオーバーヘッドが少ない • そのため、大量のスレッドを立ち上げるより軽量に動け る
Coroutineの実現方法 • そのほかにも、JobがJobを作成していた場合の親子 関係や、実行できるスレッドのScopeやContextなどの 考えがある
Kotlin/Nativeの謎
Kotlin/Nativeの謎 Native周りのコードにlauchなどが見当たらない。
Kotlin/Nativeの謎 Kotlin → LLVM中間コードの コンパイラが見つからないので、 まさか直に置き換えている?🤔
Kotlin/Nativeの謎 それ以外の、Worker/Jobの概念は一緒。 Objective-C++で書かれているので、 iOS/Linuxなど複数プラットフォームをこれで対応して いる?
まとめ
Coroutineとは • Coroutineは古くからある手法で、プログラミング言語の実 装として実現されている • そのため、少ないリソースで非同期処理を実現している • また、プログラミング言語さえ動けばOS環境は不問 • Kotlinでは、JVMのスレッド処理とステートマシンによって
非同期な処理を実現している。
以上、ありがとうございました!
参考資料 • Asynchronous Programming with coroutines