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
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
90
Not 2 L8 JKでもわかるMaterial 3
bigbackboom
0
80
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
属人化したISMS運用をGitHubとAIで仕組み化した1年間の記録
sioncojp
4
2.1k
DBTS2026 盛り上がってますか!?Databricksが実現するAI時代のデータ基盤
akuwano
1
200
2026-11-11 Tamachi.sre#7 PaCにインフラリソースの命を救われました。 / PaC saves the infra resource life
masasuzu
0
110
[General] 개발자로 해외 기업에서 일하기
skydoves
1
330
田んぼの見回りをIoTで減らしたい!水位監視から電池駆動カメラまでの試行錯誤
itosoft
1
120
Kiro CLI 入門 (ターミナルと CI で使う) | 目指せ Kiro マスター 03
inariku
PRO
2
130
【Oracle AI SPOTLIGHT ウェビナー】【特別開催:日本語で解説!】Oracle AI World 2026 最新情報フィードバック
oracle4engineer
PRO
1
130
GCASアップデート(202607-202610)
techniczna
1
250
Kiro アップデート 2026 年 11 月号 (11 月 8 日時点) | 目指せ Kiro マスター アップデート編
inariku
PRO
2
100
llm-d に入門してみた / Try out llm-d
kota2and3kan
0
110
The Author Pays
hiccupps
0
160
evcc & Home Assistant
naltatis
0
530
Featured
See All Featured
A better future with KSS
kneath
240
18k
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
330
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
2
440
Designing Powerful Visuals for Engaging Learning
tmiket
1
650
The untapped power of vector embeddings
frankvandijk
2
2k
From π to Pie charts
rasagy
1
440
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
310
Exploring anti-patterns in Rails
aemeredith
4
560
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.4k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
460
The Cult of Friendly URLs
andyhume
79
7.1k
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