Concurrency
Task
(idel time 부여)
ex) try? await Task.sleep(for: .milliseconds(500))
Actor
protocol Actor : AnyActor
[ ] https://sujinnaljin.medium.com/swift-actor-뿌시기-249aee2b732d 추가 공부 필요!
병렬 프로그래밍에서 데이터 경합(Data Race) 문제를 줄이기 위해 고안되었다.
- 동기화된 상태 관리
: actor 내부의 상태는 actor 자신만이 직접 접근할 수 있으며, 다른 코드가 접근하려면 actor의 메서드를 통해야 합니다. 이렇게 하면 동시성 문제를 피할 수 있습니다. - 직렬화된 접근
: actor의 메서드는 한 번에 하나의 쓰레드만 접근할 수 있도록 직렬화됩니다. 따라서 동일한 상태에 동시에 여러 쓰레드가 접근할 일이 없어집니다. - 비동기 메서드 호출
: actor의 메서드는 비동기적으로 호출됩니다. 이는 async/await 패턴을 사용하여 비동기 작업을 간편하게 처리할 수 있도록 합니다.
MainActor
@globalActor final actor MainActor
main Dispatch Queue 내에서 실행되도록 명시한다.
직접 DispatchQueue.main.async 를 호출할 필요가 없다.
ex) UILabel, UIViewController 도 @MainActor 가 붙어있다.
(사용)
- class 에 명시 : 해당 클래스의 모든 function 과 property 가 메인 큐에서 자동으로 설정/호출/접근 된다.
- function 에 명시 : 해당 함수는 메인 큐에서 실행된다.
- ex) 내부로직은 메인 큐에서 실행되지만, 내부의 await 비동기 작업은 메인스레드를 보장하지 않는다.
@MainActor
func load() async {
// 1. 메인스레드 보장.
let data = await loadData()
// 3. 메인스레드 보장.
setDataToLabel(data)
}
func loadData() async {
// 2. 비동기 작업 실행
}
(주의)
- async-await 을 사용해야 유효하다.
- closure 혹은 combine 사용시 내부 로직의 main thread 를 보장하지 않는다. ayns-await 와 다른 동시성 모델이기 때문.
@MainActor // 🙂
class ListViewModel: ObservableObject {
func load() {
loader.loadItems { [weak self] result in
/*
😰
@MainActor 가 붙어 함수 자체는 메인스레드에서 호출되지만,
closure 내부는 백그라운드에서 수행된다.
*/
self?.result = result
}
}
}
preconcurrency
주로 objective-c 와 상호 작용하는 코드에서 사용한다.
Objective-C에서는 동시성 모델이 Swift와 다르기 때문에, 이 속성을 사용하여 경고를 억제하고 호환성을 유지한다.
'Swift' 카테고리의 다른 글
Attribute Wrapper (0) | 2024.08.01 |
---|