1. 들어가기 전에
GCD를 공부하기 전에 우리는 Queue
라는 자료구조를 알고있습니다.
먼저 들어온 놈이 먼저 처리된다.. 라는건데 매표소에 줄을 서서 티켓을 산다고 생각하시면 편합니다.
이걸 먼저 얘기하는 이유는 앞으로의 내용이 큐와 연관되어있기 때문입니다!
2. GCD와 Dispatch Queue
GCD(Grand Central Dispatch)
는 스레드에 대한 관리를 개발자가 아닌 OS에서 처리할 수 있도록 애플에서 개발한 것 입니다.
GCD에선 Dispatch Queue
를 통해 작업을 관리합니다.
Dispatch Queue에는 크게 두 종류로 나뉘는데 아래에서 조금 더 살펴볼게요.
2-1. Serial Queue - Main Queue(main)
Serial Queue
등록된 작업을 순차적
으로 처리하는 방식
- task 0이 끝나야만 task 1이 실행됨
- 한 번에 하나의 작업만 실행 가능함
Main Queue
: 메인 스레드에서 실행되며 Serial Queue 입니다.
모든 UI(UIKit) 처리는 메인 스레드에서 처리를 해야합니다.
그 이유는 UIApplication의 인스턴스가 main thread에서 처리되기 때문인데요
UIApplication > UIViewController > UIView > SubView(Button, TextField..) 등과 같이 chain 형태로 물려있기 때문에
모든 UI는 UIApplication의 자손격으로 볼 수 있습니다.
그렇기 때문에 모든 UI(UIKit) 처리는 메인 스레드에서 처리를 해야합니다.
// example) sync, async에 관한 부분은 아래에서 이어집니다
DispatchQueue.main.async {
updateUI()
}
2-2. Concurrent Queue - Global Queues(global)
Concurrent Queue
등록된 작업을 동시에
처리하는 방식
- task 순서와 상관없이 코드가 실행됨
Global Queues(global)
: 전체 시스템에서 공유되는 Concurrent Queue 입니다.
위에서 Concurrent Queue는 작업을 동시에 처리한다고 했었는데 Global Queues는 QoS(Quailty of Service)에 따라 우선 순위를 정해 처리할 수 있습니다.
내림차순으로 우선순위가 결정됩니다.
주로 UI 등 우선 순위를 높게하여 처리하고 싶은 경우 userInteractive, 속도가 크게 중요하지 않다면 background를 사용합니다.
// example) sync, async에 관한 부분은 아래에서 이어집니다
DispatchQueue.global(qos: .userInteractive).async {
print("global queue")
}
2-3. Custom Queues
사용자 정의 Queue 입니다.
attribute 속성 값을 통해 Serial 혹은 Concurrent Queue를 지정하여 사용할 수 있습니다.
마찬가지로 qos에 우선순위를 지정할 수도 있습니다.
let channyQueue = DispatchQueue(label: "channy", qos: .background, attributes: .concurrent)
attributes를 지정해주지 않는다면 default로 Serial Queue가 됩니다.
3. Synchronous/Asnychronous
3-1. Synchronous
Synchronous(sync)는 말 그대로 동기 처리 방식입니다.
큐에 작업을 추가했다면 작업이 끝날 때까지 기다립니다.
DispatchQueue.global().sync {
for i in 1...5 {
print(i)
}
print("==========")
}
for i in 100...105 {
print(i)
}
큐에 sync로 작업이 들어가 있고 그 아래 반복문이 있는 형태입니다.
큐의 작업이 끝나기 전에는 그 아래 코드들은 실행되지 않는 형태임을 알 수 있습니다.
3-2. Asnychronous
Asnychronous(async)는 말 그대로 비동기 처리 방식입니다.
DispatchQueue.global().async {
for i in 1...5 {
print(i)
}
print("==========")
}
for i in 100...105 {
print(i)
}
큐의 작업이 동시에 진행되므로 두 반복문의 프린트문이 섞여서 출력됩니다.
3-3. Custom async
global queue는 concurrent queue이기 때문에 동시에 큐의 작업이 실행됩니다.
커스텀으로 Serial Queue를 생성하여 async를 돌리면 어떻게 될까요?
let channyQueue = DispatchQueue(label: "channy")
channyQueue.async {
for _ in 1...5 {
print("👻")
}
print("===================")
}
channyQueue.async {
for _ in 1...5 {
print("🐻")
}
print("===================")
}
for i in 100...105 {
print(i)
}
커스텀 Serial Queue를 생성하였습니다
위 코드를 실행시키면 async라서 실행 결과는 매번 달라지지만
👻 이모지가 모두 출력된 이후에 🐻 이모지가 출력될거에요.
왜냐하면 Serial Queue는 등록된 작업이 순차적으로 실행되니까
👻 작업을 task0으로 보면 🐻 작업은 task1이니까 task0이 끝나야 task1이 실행되기 때문입니다!
틀린 부분이 있다면 댓글로 남겨주세요 😅