Grand Central Dispatch (GCD)

1 분 소요

Grand Central Dispatch (GCD)

Apple에서는 GCD라는 로우레벨 API를 제공하여 쉽게 동시작업을 처리 할 수 있다.

멀티 프로세서 기반에서 효율적인 처리를 하려면 스레드풀 패턴을 사용하여 작업들을 병렬 처리해야하지만 개발자가 직접 처리하기 까다롭다. GCD의 목적은 개발자를 스레드풀 관리 영역에서 떼어내는 것이다.

개발자는 GCD Queue에 작업들만 넣어주면 된다. 쓰레드를 생성하고, 적합한 코어에 할당하고, 쓰레드풀에서 재사용하는 모든 작업은 GCD의 책임이다.

GCD Queue

  • 한번에 한가지 task만 실행한는 Serial 방식과 동시에 task를 실행하는 Concurrent 방식을 가질 수 있다.

  • Sync 방식과 async방식으로 실행될 수 있다.

    • Serial - Sync
    • Serial - Async
    • Concurrent - Sync
    • Concurrent - Async
  • System에서 제공하는 큐가 존재한다.

    • main queue
    • global queue

main queue

  • main thread에서 동작하는 serial queue.

  • UI를 업데이트 할 때 사용한다.

  • main queue는 sync로 사용할 수 없다.

Cocoa Touch 앱에서 UIApplication 인스턴스는 main thread에 붙어있다.

UIApplication은 event loop를 관리하고 event를 처리하는 클래스이다.

앱은 UIApplication -> UIWindow -> UIViewController -> UIView -> subviews (UIButton 등) 형식의 responder chaing으로 구성되어 있으며, 이러한 일련의 event들은 main thread에서 작동한다.

  • main queue는 thread-safe하지 않다.

Apple의 디자인상 thread-safe는 퍼포먼스가 좋지 않기 때문에 대부분(100%는 아님)의 UIKit을 thread-safe하지 않게 만들었다. UIKit은 main thread 얽혀 있기 때문에 UI의 변경은 main thread에서 작업하면 쉽고 효율적인 코딩이 가능하다.

DispatchQueue.main.async {    
    //code
}

global queue

  • 전체 시스템에서 동작하는 concurrent queue.
  • QoS(Quality of Service) 를 사용하여 우선순위를 부여할 수 있다.
DispatchQueue.global().async {    
    //code
}

Quality of Service(QoS)

  1. User-interactive: 즉시 완료해야 하는 UI 조작이나 대기 시간이 적은 작업. 메인 스레드에서 작업해야한다.
  2. User-initiated: UI의 비동기작업.
  3. Default : QoS를 지정하지 않으면 중간 수준의 우선순위로 적용한다.
  4. Utility: 네트워크나 계산등의 시간이 오래걸리는 작업.
  5. Background: 사용자가 알지 못하는 작업.

qos

출처 : https://www.allaboutswift.com/dev/2016/5/21/gcd-with-qos-in-swift

custom queue

// serial queue : 기본값은 serial로 동작
let customQueue = DispatchQueue(label: "com.example.customQueue")
customQueue.async {
    //code
}

// concurrent queue : .concurrent 명시
let customQueue = DispatchQueue(label: "com.example.customQueue", qos: .userInitiated, attributes: .concurrent)
customQueue.async {
    //code
}

DispatchGroup

여러가지 작업들을 관리하고 모니터링 할 수 있다.

모든 작업이 완료되어야 진행하는 로직을 짜는데 도움이 된다.

DispatchSemaphore

전통적인 counting semaphore를 사용하여 리소스의 접근을 제한할 수 있다.

예를들어 mp3파일을 다운받는 프로그램에서 동시에 3개의 다운로드만 가능하도록 제한하기 위해 Semaphore를 사용할 수 있다.

let queue = DispatchQueue(label: "com.gcd.myQueue", attributes: .concurrent)
let semaphore = DispatchSemaphore(value: 3)
for i in 1 ... 15 {
    queue.async {
        let songNumber = i
        semaphore.wait()
        print("Downloading song", songNumber)
        sleep(2) // Download take ~2 sec each
        print("Downloaded song", songNumber)
        semaphore.signal()
    }
}

참고 사이트

https://developer.apple.com/documentation/dispatch

https://www.raywenderlich.com/5370-grand-central-dispatch-tutorial-for-swift-4-part-1-2

https://zeddios.tistory.com/519#recentComments

카테고리:

업데이트:

댓글남기기