Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Swift Concurrencyとレースコンディション
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Yuki Yasoshima
August 25, 2024
Programming
810
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Swift Concurrencyとレースコンディション
After iOSDC Japan 2024
2024/8/26
Yuki Yasoshima
August 25, 2024
More Decks by Yuki Yasoshima
See All by Yuki Yasoshima
空間オーディオの活用
objectiveaudio
0
200
Swift Concurrency - 状態監視の罠
objectiveaudio
2
870
モーダルの遷移を理解する
objectiveaudio
4
2.9k
オーディオ波形を表示するために知っておくべきこと
objectiveaudio
0
1.2k
AVAudioEngineでリアルタイムレンダリング
objectiveaudio
1
950
リファクタリング・チャレンジ リバーシ編
objectiveaudio
0
210
UIKitは2度ベルを鳴らす
objectiveaudio
0
370
iOSDC2018.pdf
objectiveaudio
1
2.4k
Objective-C++を使ってMRCで快適に開発する
objectiveaudio
0
24k
Other Decks in Programming
See All in Programming
数年滞っていたダークモード対応をおよそ2週間で完了させる
chigichan24
0
680
DroidKaigi 2026 「個人開発という実験場: Android エンジニアが手にする4つの自由」
slashnephy
0
220
型解析で実現する Go の言語内 DSL / Conference に Go! タイムテーブルの歩き方 for Gophers
mazrean
0
130
スマート反転とウェブアクセシビリティ
camiha
0
100
AWS Step Functions 大規模並列の壁を越える / jaws-sonic-2026-niigata-step-functions
kasacchiful
PRO
0
380
FastAPI の並行処理モデルを完全に理解する
hoto17296
9
3.8k
[KotlinConf Extended South Korea 2026] KotlinConf 2026 발표자 후기
wisemuji
0
100
Hono + Inertia + React で LP を構築した話
oukayuka
2
210
20260828_品質と開発生産性を両立させる、AI時代のE2Eテストの考え方
magicpod
0
160
AI時代に学ぶ 好きなルール 嫌いなルール Linter編
shorty5121
0
860
バグを直したら useEffect が消えた
colorful12
3
840
異なる設計思想のフレームワークを経験して得た学び
amekuhideki
2
1.5k
Featured
See All Featured
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
340
Thoughts on Productivity
jonyablonski
76
5.4k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.6k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
530
Designing for Performance
lara
611
70k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.8k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.9k
Everyday Curiosity
cassininazir
0
310
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
310
Transcript
:VLJ:BTPTIJNB!ZBTP@TBO 4XJGU$PODVSSFODZͱ ϨʔείϯσΟγϣϯ "GUFSJ04%$+BQBO
ඇಉظॲཧͰى͖Δ w σʔλڝ߹ w ϨʔείϯσΟγϣϯ ؒҧͬͨίʔυΛॻ͍ͯେͳ͘ಈ͍ͯ͠·͏
4XJGU$PODVSSFODZͰʁ w 4XJGU$PODVSSFODZ͕ίϯύΠϧ࣌ʹอূ͢Δͷσʔλڝ߹·Ͱ w ϨʔείϯσΟγϣϯͷɺ ҎલͱมΘΒ࣮ͣऀ͕ؾΛ͚ͭΔඞཁ͕͋Δ
4XJGU$PODVSSFODZͷΈ w "DUPSSFFOUSBODZʢ"DUPSͷ࠶ೖՄೳੑʣ w $PPQFSBUJWF5ISFBE1PPMʢڠௐతεϨουϓʔϧʣ
nonisolated func asyncMethod(_ value: Int) async -> Int { ...
} ... Task { @MainActor in let value = makeValue() let result = await asyncMethod(value) print("result : \(result)") } ॲཧ͕ܧଓ࣮ͯ͠ߦ͞ΕΔ୯Ґ ᶃ ᶄ ᶅ ᶃϝΠϯ ᶄ#( ᶅϝΠϯ 4VTQFOUJPO1PJOU εϨου $POUJOVBUJPO ϝΠϯ
nonisolated func asyncMethod(_ value: Int) async -> Int { ...
} ... Task { @MainActor in let value = makeValue() let result = await asyncMethod(value) print("result : \(result)") } ॲཧ͕ܧଓ࣮ͯ͠ߦ͞ΕΔ୯Ґ ᶃ ᶄ ᶅ ᶃϝΠϯ ᶄ ᶅϝΠϯ 4VTQFOUJPO1PJOU εϨου $POUJOVBUJPO ᶄ ᶄ
$PPQFSBUJWF5ISFBE1PPM ڠௐతεϨουϓʔϧ εϨου εϨου ࣮ߦͪ "DUPSᶃ "DUPSᶄ /PO*TPMBUFE Task {
@MainActor in let value = makeValue() let result = await asyncMethod(value) return "fetched : " + result } Task { } 5BTLͷ࣮ߦ
nonisolated func method() { ᶃ Task.detached { ᶄ } Task.detached
{ ᶅ } ᶆ } ࣮ߦ͞ΕΔॱ൪ w ᶄɺᶅɺᶆฒྻͰ࣮ߦ͞ ΕΔ શͯ/PO*TPMBUFEͷ߹ ᶃ ᶆ ᶄ ᶅ εϨου
nonisolated func method() { ᶃ Task.detached { ᶄ } Task.detached
{ ᶅ } ᶆ } ࣮ߦ͞ΕΔॱ൪ w ᶄɺᶅɺᶆฒྻͰ࣮ߦ͞ ΕΔ w ᶆͷޙʹᶄɺᶅ͕ಉ͡εϨ ουͷՄೳੑͳ͘ͳ͍ શͯ/PO*TPMBUFEͷ߹ ᶃ ᶆ ᶄ ᶅ εϨου ᶄ ᶅ
@MyActor func method() { ᶃ Task { @MyActor in ᶄ
} Task { @MyActor in ᶅ } ᶆ } w ·ͣᶃɺᶆ͕࣮ߦ͞ΕΔ w ᶄɺᶅ ฒྻʹ࣮ߦ͞Εͳ͍͕ ͲͪΒ͔Β ࣮ߦ͞ΕΔ͔Θ͔Βͳ͍ ࣮ߦ͞ΕΔॱ൪ ಉ͡"DUPSͷ߹ εϨου ᶃ ᶆ ᶄ ᶅ ᶄ ᶅ ʁ
ͷ͋ΔίʔυΛվળ͢Δ
ͷ͋Δίʔυྫ λοϓͨ͠ͷϩάΛૹΔ w λοϓ͢ΔͨͼʹϩʔΧϧʹอ͍࣋ͯ͠ΔΛ૿͢ w ఆظతʹΛαʔόʔʹૹ৴͢Δ w ૹ৴ͨ͠ΒϩʔΧϧͷΛϦηοτ͢Δ
ͷ͋Δίʔυྫ actor Counter { var count: Int = 0 func
increment() { count += 1 } func reset() { count = 0 } } class CountLogger { private let counter = Counter() func increment() async { await counter.increment() } // ఆظతʹؒΛ͓͍ͯݺΕΔఆ func post() async { let count = await counter.count await postCountLog(count) await counter.reset() } }
class CountLogger { func increment() async { ... } ...
func post() async { let count = await counter.count await postCountLog(count) await counter.reset() } } w DPVOUऔಘ͔ͯ͠ΒSFTFU͢Δ·ͰͷؒʹJODSFNFOU ͕ݺΕΔͱ ͦͷ૿ՃQPTU͞ΕͣʹSFTFU͞ΕΔ
class CountLogger { func increment() async { ... } ...
func post() async { let count = await counter.count await counter.reset() await postCountLog(count) } } w DPVOUऔಘޙʹ͙͢SFTFUͯ͠ɺ 4VTQFOUJPO1PJOUͰJODSFNFOU͕ݺΕΔՄೳੑ͕͋Δ
actor CountLogger { func increment() async { ... } ...
func post() async { let count = await counter.count await counter.reset() await postCountLog(count) } } w BDUPSʹͯ͠4VTQFOUJPO1PJOU͕ೖΔ͜ͱมΘΒͳ͍
վળͨ͠ίʔυ actor Counter { private var count: Int = 0
func increment() { count += 1 } func pull() -> Int { let count = self.count self.count = 0 return count } } actor CountLogger { private let counter = Counter() func increment() async { await counter.increment() } // ఆظతʹؒΛ͓͍ͯݺΕΔఆ func post() async { let count = await counter.pull() await postCountLog(count) } }
actor Counter { private var count: Int = 0 ...
func pull() -> Int { let count = self.count self.count = 0 return count } } w DPVOUͷऔಘͱϦηοτΛBDUPSͷϝιουͭͰߦ͏͜ͱͰ 4VTQFOUJPO1PJOU͕ೖΔ͜ͱͳ͘ͳΔ
αϯϓϧͷ༷มߋ λοϓͨ͠ͷϩάΛૹΓ߹ܭΛදࣔ w λοϓ͢ΔͨͼʹϩʔΧϧʹอ͍࣋ͯ͠ΔΛ૿͢ w ఆظతʹΛαʔόʔʹૹ৴͢Δ w ૹ৴ͨ͠ΒϩʔΧϧͷΛϦηοτ͢Δ w ૹ৴࣌ʹαʔόʔ͔Β߹ܭΛฦ͠දࣔ͢Δ
/FX
func post() async -> Int { let count = await
counter.pull() let total = await postCountLog(count) return total } w ಉ࣌ʹݺΕΔͱɺޙ͔ΒݺΜͩํ͕ઌʹऴΘΔՄೳੑ͕͋Δ w BDUPS͕ಉ͡Ͱؔͳ͍ func post() async -> Int { let count = await counter.pull() let total = await postCountLog(count) return total } ઌʹݺΜͩॲཧ ޙ͔ΒݺΜͩॲཧ
w ݺͼग़͢λΠϛϯά͕ॏෳ͢Δͱ͕ى͖ΔՄೳੑ͕͋Δ Task { let total = await logger.post() print("total
: \(total)") } ͱΓ͋͑ͣ5BTL ❓
5JNFSͰ5BTLΛ܁Γฦ࣮͠ߦ w QPTUͷॲཧ͕5JNFSͷJOUFSWBMΛ͑Δͱɺ QPTUͷॲཧ͕ॏෳ͢ΔՄೳੑ͕͋Δ Timer.scheduledTimer(withTimeInterval: 10, repeats: true) { _
in Task { let total = await logger.post() print("total : \(total)") } } ❌
w 5BTLͷதͰϧʔϓ͢ΕɺQPTUͷॲཧॏෳ͠ͳ͍ Task { while true { await logger.post() print("total
: \(total)") try await Task.sleep(for: .seconds(10)) } } 5BTLͰ܁Γฦ࣮͠ߦ
αϯϓϧͷ༷มߋ λοϓͨ͠ͷϩάΛૹΓ߹ܭΛදࣔ w λοϓ͢ΔͨͼʹϩʔΧϧʹอ͍࣋ͯ͠ΔΛ૿͢ w ఆظతʹΛαʔόʔʹૹ৴͢Δ w ૹ৴ͨ͠ΒϩʔΧϧͷΛϦηοτ͢Δ w ૹ৴࣌ʹαʔόʔ͔Β߹ܭΛฦ͠දࣔ͢Δ
w ࣗ༝ͳλΠϛϯάͰΛαʔόʔʹૹ৴͢Δ /FX
var isProcessing: Bool = false func post() { Task {
guard !isProcessing else { return } isProcessing = true let total = await logger.post() print("total : \(total)”) isProcessing = false } } ˞"DUPSಉ͡ఆ ඇಉظॲཧͷॏෳΛεΩοϓ
w ࣮ߦͤͣɺผ5BTLͰඇಉظॲཧ͕ྻʹ࣮ߦ͞ΕΔΑ͏ʹ͢Δ w ͨͩ͠ɺݺͼग़͠ଆ͕࣮ࡍͷඇಉظॲཧͷྃΛͭ͜ͱͰ͖ͳ͍ let channel: AsyncChannel<Void> Task { for
await _ in channel { let total = await logger.post() print("total : \(total)") } } Task { await channel.send(()) } "TZOD$IBOOFMΛ͏
·ͱΊ 4XJGU$PODVSSFODZͱϨʔείϯσΟγϣϯ w 4XJGU$PODVSSFOUZϨʔείϯσΟγϣϯΛ͍Ͱ͘ΕΔͷͰͳ͍ w Ή͠ΖޮΛ༏ઌͯ͠Λى͍͜͢͠Έʹͳ͍ͬͯΔ w "DUPSSFFOUSBODZ w ಉ͡BDUPSಉ࢜ͷॲཧͰɺBXBJUͰڬΈࠐ·ΕΔՄೳੑ͕͋Δ
w $PPQFSBUJWF5ISFBE1PPM w εϨουͰ࣮ߦ͞ΕΔॱ൪ɺ࣮ߦ։࢝͠Α͏ͱͨ͠ॱ൪ͱݶΒͳ͍
·ͱΊ ϨʔείϯσΟγϣϯͷରԠ w ہॴతʹҰͭͷBDUPSͷதͰBTZODؔΛΘͣʹ Ͳ͏ݺΕͯෆ߹͕ى͖ͳ͍ঢ়ଶΛ࡞Δ w BTZODؔΛΈ߹Θͤͳ͍ͱ͍͚ͳ͚Εɺ ΫϦςΟΧϧηΫγϣϯ͕ಉ࣌ʹ࣮ߦ͞Εͳ͍Α͏ʹߟྀ࣮ͯ͢͠Δ
ࢀߟ w 88%$ w .FFUBTZODBXBJUJO4XJGU w 1SPUFDUNVUBCMFTUBUFXJUI4XJGUBDUPST w 4XJGUDPODVSSFODZ#FIJOEUIFTDFOFT