Swift GCD(Grand Center Dispatch), DispatchQueue.main.sync 에서 DeadLock이 발생하는 이유
GCD란?
• 멀티 스레드 환경에서 편리하게 개발할 수 있도록 애플에서 만들어 준 기술이다!!!
• GCD 즉 동시성 프로그래밍을 지원하는 스위프트의 API가 Dispatch Queue
Sync, Async
• Sync란 Main Thread 에서 task1, task2, task3 이 있다고 가정하면 task1을 Queue에 보낸 후 종료가 되어 응답이 올 때 까지, 기다리는 것이다! 따라서 task가 순차적으로 실행이 된다
• 반대로 Async란 Main Thread 에 똑같이 task1, task2, task3, 이 있다고 가정하면 task1을 보낸 후 기다리지 않고 그냥 모든 task2, task3을 Queue에 던져 버리는 것을 말한다!
Serial, Concurrent
• Queue에도 2가지의 종류가 있는데 첫 번째는 Serial이다 사용하는 Thread가 하나일 때를 말한다. Dispatch Queue에서는 Main이 Serial로 동작한다.
• Concurrent는 Thread를 여러개 사용한다! 따라서 동시에 여러개의 task를 수행 할 수있다. Dispatch Queue에서는 Global이 Concurrent로 동작한다
그렇다면!! 총 4가지의 조합이 생긴다!
• Sync -> Serial
• Async -> Serial
• Sync -> Concurrent
• Async -> Concurrent
자 그러면 Async -> Concurrent 부터 보면 아래 그림처럼 여러개의 task를 동시에 수행할 수 있을 것이다. 왜냐? async를 통해 task를 다 던져 버리고 각각의 thread를 통해서 일을 실행하니까!
다음은 Sync -> Concurrent를 보쟈
여러 개의 Thread를 사용할 수 있지만 어짜피 Queue안에 들어 있는 Task는 1개이므로 Serial Queue와 동작하는 데 있어서 차이가 없다!
다음으로 Async -> Serial 을 보기 전에 확인 해야 할 것이 Main Queue는 Serial이라 사용하는 Thread가 하나인데 그 하나가 바로 MainThread이다!!!
그림을 통해 확인 해보자
먼저 Main Thread에서 Async 임으로 Main Queue에 순차적으로 Task1, Task2, Task3를 던져 주게 된다. 그런 후 Main Queue에서 Main Thread 한테 Task1 실행 해줘! Task2실행 해줘! Task3실행 해줘! 가 되는 것이다.
예제 코드를 보면서 확인해보자!
DispatchQueue.main.async { // 보내 버리고 다음 작업 실행
for i in 1...100 {
print(i, terminator: " ")
}
}
for i in 101...200 {
print(i, terminator: " ")
}
// 101~200 출력후 1~100출력
Main Thraed에서 두 반복 문이 순차적으로 실행 되는 상황에서 첫 번째 반복문을 Main Queue로 보내 버린 후 두 번 째 반복문이 실행되고 Main Queue에서 다시 첫 번째 반복문을 Main Thread로 요청하게 되는 것이다.
마지막으로 Sync -> Serial을 확인해 보자
먼저 Main Thread에서 Task1을 Main Queue로 보내고 Sync 임으로 Task1의 수행이 끝날 때 까지 기다린다.
다음으로 Main Queue에서 Task1의 수행을 Main Thread 한테 부탁하게 되는데 Main Thread는 Task1이 오기 전 까지 동작을 수행 할 수 없는 상태이므로 DeadLock이 발생하게 된다!