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()
}