<h1><center> iOS interview 4 </center></h1>
###### tags: `π» λ©΄μ μ§λ¬Έ`
###### date: `2025-09-2017:21:33.284Z`
> [iOS interview](https://github.com/JeaSungLEE/iOSInterviewquestions)
# Async-await
# Swift Concurrencyμ κΈ°λ³Έ λμ κ°λ
> κ·Έ μ μ.. Concurrencyλ? μΌλ°μ μΈ κ°λ
, λ€λ₯Έ μΈμ΄λ νλ«νΌμμλ ν΅μ©λλ μΌλ°μ μΈ...
- 'μ¬λ¬ μμ
μ λμμ λ€λ£¨λ κ²'
``` gemini
Concurrency (λμμ±)
νλμ CPU μ½μ΄κ° μ¬λ¬ μμ
μ λ²κ°μ κ°λ©° μ€ννλ λ°©μ. => gcd, swift concurrencyλ μ΄κ±Έ μννλ€. κ·Έλ°λ°, μλ λ°©μμ΄ λ€λ₯΄λ€.
μλ₯Ό λ€μ΄, μλ λ¬Έμλ₯Ό μμ±νλ©΄μ λμμ μμ
μ λ£λ κ²½μ°, CPUλ μλ νλ‘μΈμ±κ³Ό μμ
μ¬μ μμ
μ λ§€μ° μ§§μ μκ° λ¨μλ‘ λΉ λ₯΄κ² μ ννλ©° μ€νν΄μ.
λμμ μ§νλλ 'κ²μ²λΌ' 보μ΄λ κ²μ΄ ν΅μ¬μ΄μμ.
```
μμ
μ λ¨μλ₯Ό CPUλ ThreadλΌλ 곡κ°μμ μ²λ¦¬νλ€.
1. gcd μ΄λ»κ² λμνλ?
- Grand Central Dispatch
- GCD -> Async/Await ? Thread Explosion λ§κΈ° μν¨ why? Context Switching
- GCD -> Threadλ₯Ό CPUκ° κ°μμΌλ‘ μ¬λ¬ κ°λ₯Ό λ§λ€ μ μλ€.
- λμμ±μ μ 곡νκΈ° μν΄μ
- how? μ¬λ¬ μμ
λ€μ λ°μμ context switchingμ μ΄μ©ν΄μ λ€λ₯Έ μ°λ λλ‘ λμ΄κ°μ cpuκ° μμ
μ νλ€. κΈ°μ‘΄μ μμ
μ€μ΄λ μ°λ λλ?
- λ¬Έμ μ : 1. (λ΄λΆ Threadμμ) context switchingμ΄ μΌμ΄λλ€. | 2. κΈ°μ‘΄ μμ
μ΄λ κ°μμ μ°λ λλ κ³μ λ¨μμλ€... => μ°λ λ νλ° | 3. μ°μ μμκ° μ μ μ§μΌμ§
2. swift concurrencyλ μ΄λ»κ² λμνλ?
- Swift Concurrency -> CPUλΉ Threadκ° νλλ§ μ‘΄μ¬ν©λλ€. | **νλ ₯μ Thread Pool** <-> **μ μ ν(GCD)**
μμ
μ λΉλκΈ° μμ μ΄ λ°μνλ©΄ μμ€ν
(OS)μ λκΈ΄λ€. - await
```swift
let task = Task {
// prevA
let a = await fn();
// prevB
let b = fn2();
// prevC
let c = await fn();
}
task.cancel()
// => CPU0 - [prevA]await [....] [a prevB b prevC] await [....] []
let queue = DispatchQueue(label: "queue")
let a = DispatchWorkItem()
let b = DispatchWorkItem()
let c = DispatchWorkItem()
// => Thread0 [prevA]
// => Thread1 ------- [a prevB prevC]
// => Thread2 -----------------------[c] |
queue.task {
}
```
----
## Taskμ async-await
- What is Task? β **`βλΉλκΈ°μ μΈ μμ
μ€ν λ¨μλ₯Ό λ§λλ κ²β`**
- λ©νλ°μ΄ν° μμ: μ΄ μμ
μ΄ μ΄λ μ°λ λμμ λμνλμ§, μ°μ μμ, λ‘컬 λ³μ
- TaskLocal https://developer.apple.com/documentation/swift/tasklocal
```swift
enum Example {
@TaskLocal
static var traceID: TraceID?
}
func read() -> String {
if let value = Self.traceID {
"\(value)"
} else {
"<no value>"
}
}
await Example.$traceID.withValue(1234) { // bind the value
print("traceID: \(Example.traceID)") // traceID: 1234
read() // traceID: 1234
async let id = read() // async let child task, traceID: 1234
await withTaskGroup(of: String.self) { group in
group.addTask { read() } // task group child task, traceID: 1234
return await group.next()!
}
Task { // unstructured tasks do inherit task locals by copying
read() // traceID: 1234
}
Task.detached { // detached tasks do not inherit task-local values
read() // traceID: nil
}
}
```
```swift
let taskA = Task { @MainActor in
let a = await fnA();
}
let taskB = Task { @MainActor in
let b = await fnB();
}
let taskC = Task { @MainActor in
let c = await fnC();
}
actor A {
@MainActor
func a() {
}
}
```
```swift
func A() async {
print("a")
print("b")
await B()
}
func B() async {
print("c")
print("d")
await C()
}
func C() async {
print("e")
print("f")
}
func run() async {
print("run μ€νλ¨")
}
Task { @MainActor in
A()
}
Task {
runt()
}
// μΆλ ₯ a
// μΆλ ₯ b
```
> νλμ μ€λ λμμ μ€ν
> [a,b,c] -> [c, b, a] => [b,c,a]
- (μ€ν μλ£μ μμ 보μ₯μ΄ μλλ€)
- Task vs Task.detached => λ³λ ¬ μμ
μ ν΄μ€
- λΉκ΅¬μ‘°μ λμμ±
- Task: λ©νλ°μ΄ν° μμ
- Task.detached: λ©νλ°μ΄ν° μμ x
```swift
let parentTask: Task<Void, Error> = Task {
let taskA = Task {
print(Task.isCancelled)
return "Wow"
}
let taskB: Task<String,Error> = Task {
print(Task.isCancelled)
return "Hello"
}
await [taskA.value, taskB.value]
}
parentTask.cancel()
func childrenRun() async {
print(Task.isCancelled)
}
let asyncTask = Task {
async let children1 = childrenRun() // μ¬κΈ°μ λ³λ ¬λ‘ μλν¨
async let children2 = childrenRun() // μ¬κΈ°μ λ³λ ¬λ‘ μλν¨
// await children1 // μλμ΄ μ΄λ―Έ λ€ λμμΌλ©΄ κ° λκΈ°κ³ , μλλ©΄ μμ
μλ£λ λλ‘ κ° λκΉ...
// await children2
await [children2, children1] // λ°°μ΄μ΄ μ±μμ§ λ κΉμ§ κΈ°λ€λ¦°λ€..
}
asyncTask.cancel()
```
- async let vs withTaskGroup => λ³λ ¬ μμ
μ ν΄μ€
- ꡬ쑰μ λμμ±
-
- What is async-await
- μμ
μμλ₯Ό μλ λ°©λ²?
- awaitλ₯Ό ν λ call stack
- λ©ν λ°μ΄ν°λ 무μμΈκ°?
- Task.detached()
- μ€λ λ ν
- Task.yield()
- https://engineering.linecorp.com/ko/blog/about-swift-concurrency-performance
```swift
Task { @MainActor
for i in 1200000000 {
if i % 10 == 0 {
Task.yield()
}
print(i)
}
}
```
### μ€λ ν κ²κ³Ό μ’ λ λ΄μΌν κ²
1. TaskLocal => λ°μΈλ©, TCA κ°λ
- μ€μ λ‘ μ°λ μ¬λ‘...
### λ€μμ ν κ²
1. βοΈ **Shared Mutable State**
2. Task isolation
3. Race Condition λ¬Έμ
4. Sendable
5. actor κ°λ
λ§...
## Actor / AsyncStream
- AsyncStream?