GCD
Serial vs Concurrent
은행을 예로 들자면, Serial의 경우는 한 명의 은행원이 있고, 한 줄의 대기라인이 존재한다고 볼 수 있다. 반면 Concurrent는 한 명의 은행원은 같지만, 한 줄이 아닌 여러줄의 대기라인이 존재한다. Serial의 경우 번호표를 뽑고 기다리면, 번호 순서대로 부른다. Concurrent의 경우에는 순서대로 번호표를 주지만, 반드시 번호순대로 불리진 않는다. (중요도가 존재하기 때문)

Sync vs Async
Sync와 Async의 차이는 현재 코드가 실행 완료되기 전까지는 다음 라인을 실행하지 않느냐 마느냐 하는 것이다. Sync는 큐에 추가한 작업이 끝나기 전까지 다음 코드를 실행하지 않는다.
Serial - Sync
func test() {
let serialQueue = DispatchQueue(label: "myQ")
serialQueue.sync {
for i in 0...100 {
print(i)
}
print("a")
}
print("b")
}
// 결과
0
1
2
.
.
.
100
a
b
우선 위 코드는 Serial Queue이기 때문에 한 줄로 실행코드들이 대기한다. (for-in문, print("a") 순서)
그리고 Sync이기 때문에 Queue에 추가된 for-in문과 print("a")가 끝날때까지 print("b")가 실행되지 않는다.
Serial - Async
func test() {
let serialQueue = DispatchQueue(label: "myQ")
serialQueue.async {
for i in 0...100 {
print(i)
}
print("a")
}
print("b")
}
// 결과
b
0
1
2
.
.
.
100
a
위 코드도 Serial Queue이기 때문에 한 줄로 실행코드들이 대기한다. (for-in문, print("a") 순서)
그리고 Async이기 때문에 Queue에 추가된 for-in문, print("a")를 기다리지 않는다.
Concurrent - Sync
func test() {
DispatchQueue.global().sync {
for i in 0...100 {
print(i)
}
print("a")
}
print("b")
}
// 결과
0
1
2
.
.
.
100
a
b
위 코드는 우선 ConcurrentQueue이다. 즉 여러 줄을 만든다. 이때 줄을 결정하는 것은 별도의 중요도를 지정하지 않으면 시스템이 알아서 배치한다.
Sync이기 때문에 Queue에 등록된 for-in문과 print("a")가 끝날때까지 print("b")는 실행되지 않는다.
Concurrent - Async
func test() {
DispatchQueue.global().async {
for i in 0...100 {
print(i)
}
print("a")
}
print("b")
}
// 결과
0
b
1
2
.
.
.
100
a
위 코드는 마찬가지로 Concurrent Queue라서 줄을 멋대로 선다. 또 Async 이므로 Queue에 등록된 코드가 끝날때까지 기다리지 않는다.
Concurrent - Async QoS 지정
func test() {
DispatchQueue.global().async {
DispatchQueue.global(qos: .background).async {
for i in 0...100 {
print(i)
}
}
DispatchQueue.global(qos: .userInteractive).async {
print("a")
}
}
print("b")
}
// 결과
a
b
0
1
.
.
.
100
원래의 경우라면 마음대로 줄을 서야할 concurrent이지만, print("a")의 경우 userInteractive 즉 최우선 중요도로 지정했고, for-in문은 최하로 지정했다.
또 Async이기 때문에 Queue에 등록된 코드 실행 완료를 보장하지 않고 print("b")가 실행된다.
DispatchGroup
DispatchGroup을 사용해서 해당 Queue 그룹을 만들고 관리할 수 있다.
// 커스텀 그룹 생성
let customGroup = DispatchGroup()
// Serial Queue 생성
let q1 = DispatchQueue(label: "customQueue")
let q2 = DispatchQueue(label: "customQueue")
// customGroup에 진입
customGroup.enter()
q1.async {
print("q1 done")
customGroup.leave() // customGroup에서 이탈
}
customGroup.enter()
q2.asyncAfter(deadline: .now() + 5) {
print("q2 done")
customGroup.leave()
}
// parameter queue는 무슨 역할인지 모르겠음. DispatchQueue.main, DispatchQueue.global(), CustomDispatchQueue 등
// 다양한 Queue를 넣어봐도 아무것도 달라지지 않음.
// 애플 문서에도 설명도 없고 쓰이지 않는 parameter 인듯...
customGroup.notify(queue: q1) {
print("customGroup done.")
}
// 결과
q1 done
q2 done
customGroup done.