[GCD]
GCD: 우리가 Queue에 작업을 보내면 그에 따른 Thread를 적적히 생성해서 분배해주는 방법
GCD에 대해서 자세히 말하자면 어느 Task를 어느 Thread가 할 것인지, Mutil - Thread로 할 것인지, Sync으로 할지, Async로 할지 등을 처리하는 API
queue: OS자체에서 다른 Thread들에게 일을 분산처리 해주는 곳 (선입선출) - GCD에서 사용하는 queue의 이름은 Dispatch Queue 이다.
즉, Dispatch Queue에서 작업이 추가되면 GCD는 작업에 맞는 Thread를 자동으로 생성해서 실행하고, 작업이 종료되면 Thread를 제거하게 된다.
이제 그림을 나타내면 아래와 같다.
코드로 작성해본다면
DispatchQueue.global().async {
//Task
}
//코드의 뜻: global dispatch queue에 비동기로 task를 보낸다
//Task: 작업의 한 단위 / Task는 하나의 작업 뭉탱이이기 때문에 그 안의 동작들은 순서대로 처리가 된다.
[동기]
1. 동기의 정의
같을 동(同), 기약할 기(期) 즉, 같은 기간 또는 같은 주기라는 뜻이다.
쉽게 생각하면 그냥 코드순서대로 이루어진다고 생각하면된다.
예를 들어 자막과 영상의 시점을 맞추는 일을 우리는 무엇이라할까? 싱크를 맞춘다고 한다. 이처럼 동기가 영어로는 Synchronous라고 한다. (iOS에서는 sync)
2. 예를 들어보자.
아래의 사진처럼 Main Thread는 Dispatch Queue에 Task1을 보내고 GCD는 Task1을 받아서 다른 Thread에게 넘긴다. 이 때 Main Thread는 다른 Thread가 Task1을 끝낼 때까지 기다리고 Task1이 끝나면 Task2를 시작한다.
[비동기]
1. 비동기의 정의
비동기는 동기의 반대 개념이다. 과연 어떤 부분이 반대일까?
영어로는 Synchronous의 반대 Asynchronous라고 한다. (iOS에서는 async)
2. 예를 들어보자
아래의 사진처럼 Main Thread는 Dispatch Queue에 Task1을 보내고 GCD는 Task1을 받아서 다른 Thread에게 넘긴다. 이제 Main Thread는 Task1을 신경쓰지 않고 남아있는 Task2를 시작한다.
Main Thread가 Dispatch Queue에 Task를 넘기고 GCD는 이 Task를 다른 Thread를 생성해서 실행키는데 이 과정에는 총 2가지 직렬 / 동시가 있다.
[직렬]
현재 Serial(직렬) Queue라면 아래의 사진과 같이 GCD가 한 Thread에만 업무를 실행시킨다.
iOS Serial(직렬)은 Main이다.
[동시]
현재 Concurrent(동시) Queue라면 아래의 사진과 같이 GCD가 여러 Thread에 업무를 분담한다.
iOS Concurrent(동시)는 global이다.
❓보기에는 동시가 좋은거 같은데 동시만 써야할까? 직렬은 언제 쓰는게 좋을까? 라는 의문이 생긴다. ❓
어떤것을 사용할지는 작업의 순서 중요도에 달려있다.
Serial Queue
- Serial(직렬) Queue에 담긴 Task들은 오직 하나의 Thread에만 분배된다. 모든 Task 직전의 Task가 끝나길 기다렸다가 하나씩 실행되기 때문에 Task의 시작과 종료에 대한 순서 예측이 가능하다.
Concurrent Queue
- Concurrent(동시) Queue에 담긴 Task들은 여러개의 Thread로 분배된다. 선입선출이라는 Queue의 특성상 작업들이 순서대로 실행되어 시작되는 순서는 예측이 가능하지만 종료되는 순서는 예측이 불가능하다.
따라서 순서는 중요하지 않고 시간 절약이 목적이라면 Concurrent(동시) Queue사용이 좋고 순서가 중요한 작업들을 처리하는 (늦게 들어온 것이 먼저 끝나는)상황 방지가 목적이라면 Serial(직렬) Queue을 사용하는 것이 좋다.
[개념의 오류]
이 글을 읽었다면 serial — sync , async — concurrent 이렇게 연관이 있는건가? / 비동기(Async)란 말과 동시(Concurrent)란 말이 같은 말인가? 와 같은 의문이 생길 수 있다. 하지만 이 질문의 답은 모두 "아니다." 이다.
async(비동기) vs sync(동기)
- 작업을 보내는 시점에서 기다릴지 말지에 대해 다루는 것
concurrent(동시) vs serial(직렬)
- Queue(대기열)로 보내진 작업들을 여러개의 스레드로 보낼 것인지 한개의 스레드로 보낼 것인지에 대해 다루는 것
4가지 조합
-
SerialQueue.sync : 메인 스레드의 작업 흐름이 queue에 넘긴 태스크가 끝날때까지 멈춰있고(sync), 넘겨진 task는 queue에 먼저 담겨있던 작업들과 같은 스레드에 보내지기 때문에 해당 작업들이 모두 끝나야 실행 (Serial Queue)
-
ConcurrentQueue.sync : 메인 스레드의 작업 흐름이 queue에 넘긴 태스크가 끝날때까지 멈춰있고(sync), 넘겨진 task는 queue에 먼저 담겨있던 작업들과 다른 스레드에 보내질 수 있기 때문에 해당 작업들이 모두 끝나지 않아도 실행 (Concurrent Queue)
-
SerialQueue.async : 메인 스레드의 작업 흐름이 태스크를 queue에 넘기자마자 반환되고 (async), 넘겨진 task는 queue에 먼저 담겨있던 작업들과 같은 스레드에 보내지기 때문에 해당 작업들이 모두 끝나야 실행 (Serial Queue)
-
ConcurrentQueue.async : 메인 스레드의 작업 흐름이 태스크를 queue에 넘기자마자 반환되고 (async), 넘겨진 task는 queue에 먼저 담겨있던 작업들과 다른 스레드에 보내질 수 있기 때문에 해당 작업들이 모두 끝나지 않아도 실행 (Concurrent Queue)
[참고]
[iOS] 차근차근 시작하는 GCD - 1
[iOS] 차근차근 시작하는 GCD - 2
[iOS] 차근차근 시작하는 GCD - 3
[iOS] 차근차근 시작하는 GCD - 4