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
Swift Concurrencyとレースコンディション
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Yuki Yasoshima
August 25, 2024
Programming
830
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
240
Swift Concurrency - 状態監視の罠
objectiveaudio
2
910
モーダルの遷移を理解する
objectiveaudio
4
2.9k
オーディオ波形を表示するために知っておくべきこと
objectiveaudio
0
1.2k
AVAudioEngineでリアルタイムレンダリング
objectiveaudio
1
970
リファクタリング・チャレンジ リバーシ編
objectiveaudio
0
220
UIKitは2度ベルを鳴らす
objectiveaudio
0
380
iOSDC2018.pdf
objectiveaudio
1
2.5k
Objective-C++を使ってMRCで快適に開発する
objectiveaudio
0
24k
Other Decks in Programming
See All in Programming
JIS keyboard support in Omarchy
lef237
0
160
パスワード再設定メールのURLについて知っておこう
uyuki234
0
190
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
320
Agentic Software Factoryに、すごく賢いIF文を。 / super smart IF statement into the Agentic Software Factory.
rkaga
8
2.4k
最近”作らせてる” ローカルAIアプリの話
akit37
0
500
Groovy as a human and AI friendly programming language
paulk
0
120
우리의 Nitro Modules는 당신의 Turbo Modules보다 아름답다
l2hyunwoo
0
220
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
370
Event is what happens
moro
2
1.6k
Vue Fes Japan の “作る側”に関わってみて
naokihaba
1
190
残高管理から台帳サービスへの進化
artoy
1
210
Kotlinの15年とServer-Side Kotlin
n_takehata
1
170
Featured
See All Featured
Fashionably flexible responsive web design (full day workshop)
malarkey
409
67k
Raft: Consensus for Rubyists
vanstee
143
7.8k
Leo the Paperboy
mayatellez
10
2.4k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.1k
4 Signs Your Business is Dying
shpigford
187
23k
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
630
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
12k
[SF Ruby Conf 2025] Rails X
palkan
3
1.5k
A Soul's Torment
seathinner
8
3.8k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
580
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