GCD
OperationQueue vs GCD
- OperationQueue: 긴 작업, 작업 간 의존도가 높은 작업, 일시중지나 취소 등의 동작, KVO를 사용하는 프로퍼티, 객체단위 처리
- GCD: 간단하게 사용가능한 큐를 제공,타이머나 프로세스등 비동기처리에 적합
Serial, Concurrent
- Serial 큐는 1줄짜리 Queue, 앞의 작업이 종료될때까지 기다려야함, 따라서 작업 순서가 보장됨
- Concurrent 큐는 여러줄짜리 Queue, 여러 작업이 동시에 출발하므로 작업 완료 순서가 보장되지 않음
Async, Sync
- Async는 코드 흐름상에서 클로저의 코드를 실행시키도록 만들고 바로 돌아옴
- Sync는 코드 흐름이 클로저 내부로 넘어가버리고, 모두 실행된다음 밖의 코드가 실행됨
main, global
- main Queue는 Serial, UI 코드 실행, 가능하면 비우는게 좋다
- global Queue는 Concurrent로 동시에 여러개가 시작된다(시작순서는 코드순서)
- main은 serial이기 때문에 계속 앱의 UI가 계속 실행되는데 이때 sync를 걸면 데드락이 생겨 크래시가 발생한다.
작업지연
- asyncAfter(deadline:)메소드를 통해 작업을 지연시킬 수 있음
let delay = 3.0
DispatchQueue.main.asyncAfter(deadline: .now() + delay) in
print("delayed")
DispatchGroup
그룹의 작업이 모두 끝나면 알려줌
func dispatchGroup() {
let group = DispatchGroup.init()
let queue = DispatchQueue.global()
queue.async(group: group) {
print("task 1")
}
queue.async(group: group) {
print("task 2")
}
group.notify(queue: qeueue) {
// 큐가 비워지면 실행됨
print("task complete")
}
}
Semaphore
크리티컬 섹션 내 자원에 대해 한정적으로 접근할 수 있도록 함
func dispatchSemaphore() {
let queue = DispatchQueue.global()
let semaphore = DispatchSemaphore.int(value: 0) // 한 번에 하나의 작업만 허용
queue.async {
semaphore.wait(timeout: .distantFuture) // 무한정 대기하다가 signal을 받으면 실행
print("task 1 ")
semaphore.signal()
}
queue.async {
semaphore.wait(timeout: .distantFuture)
print("task 2")
semaphore.signal()
}
print("작업 시작")
semaphore.signal()
}