Coroutine
- 서브 루틴을 일시 정지하고 재개할 수 있는 프로그래밍
- 참고하기 좋은 블로그 - Swift Async-Awiat과 Kotlin Coroutine 비교
Swift Concurrency
- 병렬 프로그래밍과 비동기 코드를 사용하는 프로그램은 한번에 여러 작업을 수행할 수 있음
- Swift안에서 Concurrency 모델은 스레드에서 구축하지만 스레드와 직접 상호 작용하지는 않음
- → 비동기 함수가 Blocking이 되면 시스템에 맡김
- → 비동기 함수가 다시 resume되면 해당 함수가 어느 스레드에서 실행될지는 보장되지 않음
- → 비동기 함수가 Blocking 시 실행 중이던 스레드를 포기할 수 있게 되고, 해당 스레드는 다른 비동기 함수를 실행할 수 있음
- 이 개념은 코루틴(Coroutine) 에서 출발
- → Swift의 Async/Await 은 코루틴 모델을 적용!
- async는 함수를 suspend(중단) 시키고, 다시 resume(재개)을 할 수 있지만 한번에 한 부분의 프로그램만 실행
- async를 붙임으로 비동기 함수임을 명시
func listPhotos(inGallery name: String) async throws -> [String] { let result = // ... some asynchronous networking code ... return result }
- → error를 던지면서 비동기인 경우
- await 키워드를 만나면 스레드를 Block하고 async 메서드의 반환값을 받을 때까지 일시 중단
- → 즉, await 키워드가 중단을 시키는 지점
- → 비동기 메서드 안에 또다른 비동기 메서드가 있으면 모두 await을 명시적으로 적어줘야함
// completion handler 사용 예시
listPhotos(inGallery: "Summer Vacation") { photoNames in
let sortedNames = photoNames.sorted()
let name = sortedNames[0]
downloadPhoto(named: name) { photo in
show(photo)
}
}
// async-await 사용 예시
let photoNames = await listPhotos(inGallery: "Summer Vacation")
let sortedNames = photoNames.sorted()
let name = sortedNames[0]
let photo = await downloadPhoto(named: name)
show(photo)
- await은 코드가 실행 중단 가능한 위치에서만 호출이 가능
- 비동기 함수, 메서드, 프로퍼티, 이니셜라이즈(getter만)
- @main으로 표시된 struct, class, enum의 static main() 메서드
- Unstructed Concurrency의 unstructed child task
- await 코드들 사이의 코드는 다른 동시성 코드로 인한 방해없이 순차적으로 진행됨
- → await을 사용하면 안되는 순차적인 코드의 경우, 이를 명시하기 위해 코드를 묶어라
-
// 꼽사리가 가능한 경우 let firstPhoto = await listPhotos(inGallery: "Summer Vacation")[0] add(firstPhoto, toGallery: "Road Trip") // At this point, firstPhoto is temporarily in both galleries. remove(firstPhoto, fromGallery: "Summer Vacation") // 여기에 awiat 붙이지마라는 경우 // move는 비동기 함수가 아니기 때문에 add, remove에 await을 붙일 수 없게 됨 func move(_ photoName: String, from source: String, to destination: String) { add(photoName, toGallery: destination) remove(photoName, fromGallery: source) } // ... let firstPhoto = await listPhotos(inGallery: "Summer Vacation")[0] move(firstPhoto, from: "Summer Vacation", to: "Road Trip")
Suspend란?
- 동기 메서드는 스레드가 해당 메서드를 모두 수행했을 때 스레드에 대한 control을 잃음
- 비동기 메서드는 동작 수행 완료 시, 그리고 시스템에 의해 스레드 control을 잃을 수 있음
- 비동기 메서드가 await이 되어 결과가 반환할 때까지 기다리는 동안 실행을 일시 중단(suspend)
- → 이때 스레드 제어권(control)을 잃음
main thread ———- async를 thread1에 던짐(비동기)
thread 1 : async 호출 —- await (스레드 제어권을 놓는다) 스레드가 비워져서 다른 코드를 실행할 수 있어짐
→ 이것이 await으로 이름을 진 이유
→ 스레드가 차단되는 것이 아니기 때문에 시스템은 다른 작업을 예약할 수 있음
→ 기능이 일시중지되어 있는 동안 앱의 상태가 크게 변할 수도 있음
스레드 양보 → 스레드에 대한 제어권은 시스템에게 감
시스템 : async의 리턴값을 계산하는 작업을 다하고 다시 스레드로 돌아오지만 thread 1으로 복귀한다는 보장은 없음
→ 시스템이 async함수가 중요도가 높다고 판단하면 다시 함수 재개한다
await로 async를 호출한 경우를 언제, 몇번 일시정지가 되고 재개될지 알 수 없고, 시스템이 자체적으로 중요도와 작업 상태를 결정하는 것이기 때문에 일시정지없이 실행될 수도 있다
참고 링크
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/
728x90
'학습활동' 카테고리의 다른 글
동시성 프로그래밍 (0) | 2023.11.08 |
---|---|
Swift Concurrency II (0) | 2023.09.28 |
User Notifications (0) | 2023.09.25 |
OAuth(Open Authorization) (0) | 2023.09.21 |
Localization (0) | 2023.08.31 |