GCD(Grand central Dispatch)

Grand Central Dispatch(GCD)는 멀티 코어 하드웨어에서 동시성 코드 실행을 포괄적으로 지원합니다.


DispatchQueue

DispatchQueue는 작업 아이템의 실행을 관리합니다. 대기열에 제출된 각 아이템은 시스템에 의해서 관리된 스레드풀에 의해 처리됩니다.


Serial Queue, Concurrent Queue, Sync, Async

DispatchQueue에는 크게 Serial 과 Concurrent 두 종류가 있고, FIFO(First in First out) 순서로 처리합니다. Serial은 이전 작업이 끝나면 다음 작업을 순차적으로 실행하는 직렬형태의 Queue 이고, Concurrent는 병렬형태로 실행되는 Queue 입니다.

그리고 이것은 동기(sync), 비동기(async) 방식 중 어떻게 실행하느냐에 따라 다음 처럼 4가지 조합이 나올수 있습니다.

  • Serial - Sync
  • Serial - Async
  • Concurrent - Sync
  • Concurrent - Async

sync는 큐에 작업을 추가한후, 추가된 작업이 종료될떄가지 기다립니다. async는 큐에 작업을 추가하기만 할뿐 작업의 완료 여부는 보장하지 않습니다.

Sync-Serial/Concurrent

DispatchQueue.global().sync { print("1") }
print("2")
DispatchQueue.global().sync { print("3") }
print("4")
DispatchQueue(label:"SerialQueue").sync { print("5") }
print("6")

-------
1
2
3
4
5
6

Sync는 큐에 추가한 작업이 끝날때까지 기다렸다가 다음 코드를 수행하므로 동일한 순서를 보장합니다.

Async-Serial

DispatchQueue(label:"SerialQueue").async { print("1") }
print("2")
DispatchQueue(label:"SerialQueue").async { print("3") }
print("4")
DispatchQueue(label:"SerialQueue").async { print("5") }
print("6")

-------
2
1
4
3
6
5

위에서 언급한 결과값은 실행때마다 변하지만, 1,3,52,4,6의 순서를 고정입니다. 두 그룹의 출력 순서만 달라지게 됩니다. 214653,214365…

Async-Concurrent

DispatchQueue.global().async { print("1") }
print("2")
DispatchQueue.global().async { print("3") }
print("4")
DispatchQueue.global().async { print("5") }
print("6")

-------
2
1
4
3
6
5

여기에서 2,4,6의 출력순서만 보장되고 그 이외의 출력순서는 보장되지 않습니다. 병렬 큐에 멀티 스레드 형식으로 동작합니다.


API

MainQueue 생성

DispatchQueue.main.async { }

GlobalQueue 생성

DispatchQueue.global().sync { } // DispatchQos.QoSClass = default
DispatchQueue.global(qos: .background).async { }

Custom Dispatch Queue 생성

큐를 만들때 기본은 Serial, concurrent인 경우에 별도로 명시합니다.

// Serial Queue
DispatchQueue(label: "com.myQueue").async { }
DispatchQueue(label: "com.myQueue").sync { }

// Concurrent Queue
DispatchQueue(label: "com.myQueue"), qos: .default, attributes: .concurrent, autoreleaseFrequencyL .inherit, target: nil).async { }

asyncAfter

// Second 단위는 Double
// deadline 의 타입은 DispatchTime
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { }

/*
enum DispatchTimeInterval: Equatable {
	case seconds(Int)
	case milliseconds(Int)
	case microseconds(Int)
	case nanoseconds(Int)
	case never
	public static func == (lhs: DispatchTimeInterval, rhs: DispatchTimeInterval) -> Bool
}
*/
// 더 자세하게 하고싶다면
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)

Reference

GCD GitHub
Dispatch Documents
DispatchQueue Documents
GCD overview
giftbot님 blog
giftbot님 blog