GCD를 활용해 비동기 코드를 작성하며 자주 헷갈리는 sync, async 그리고 Serial, Concurrent를 조합했을 때 어떻게 동작하는지 그림과 함께 정리해보려고 합니다.
GCD가 무엇인지는 이 곳에서 확인 가능합니다!
Serial + Sync
var numbers = [0, 1, 2, 3, 4]
let dispatchQueue = DispatchQueue(label: "custom")
print("Serial + Sync 실행결과")
(0..<numbers.count).forEach { index in
dispatchQueue.sync {
print(numbers[index])
}
}
😨 메인스레드 데드락 주의!
메인 스레드에서 sync로 호출하면, 메인 스레드는 작업결과를 리턴받을 때까지 기다리게되고(block) 메인 스레드는 기다리느라 아무것도 할 수 없으므로 작업을 수행할 수 없습니다.
따라서, 작업은 "메인스레드야, 내 작업 해줘!" 외치고 있고,
메인스레드는 "작업결과 나올때까지 기다릴게." 하고 있는 데드락 상태에 빠지게 됩니다.
var numbers = [0, 1, 2, 3, 4]
let dispatchQueue = DispatchQueue(label: "custom")
print("데드락 발생!")
(0..<numbers.count).forEach { index in
DispatchQueue.main.sync {
print(numbers[index])
}
}
Serial + Async
var numbers = [0, 1, 2, 3, 4]
let dispatchQueue = DispatchQueue(label: "custom")
print("Serial + Async 실행결과")
(0..<numbers.count).forEach { index in
dispatchQueue.async {
print(numbers[index])
}
}
sleep(5)
serial이니까 한 스레드에 순차적으로 등록하고, 각 작업은 순서 상관없이 리턴됩니다.
Concurrent + Sync
var numbers = [0, 1, 2, 3, 4]
let dispatchQueue = DispatchQueue(label: "custom", attributes: .concurrent)
print("Concurrent + Sync 실행결과")
(0..<numbers.count).forEach { index in
dispatchQueue.sync {
print(numbers[index])
}
}
이런 경우가 있나 싶네요..?
Concurrent + Async
var numbers = [0, 1, 2, 3, 4]
let dispatchQueue = DispatchQueue(label: "custom", attributes: .concurrent)
print("Concurrent + Async 실행결과")
(0..<numbers.count).forEach { index in
dispatchQueue.async {
print(numbers[index])
}
}
sleep(5)
numbers의 갯수가 너무 작아서 순차적으로 출력되는 것처럼 보이지만 갯수만 많아지면 순서가 뒤죽박죽이 됩니다.
'iOS' 카테고리의 다른 글
View Draw Cycle (4) | 2024.10.07 |
---|---|
왁뮤 3.0 출시 및 장애 대응 기록 (8) | 2024.09.07 |
캐시 데이터 용량 표시 방식 개선하기: ByteFormatter (0) | 2024.07.29 |
GCD 공식문서 읽고 정리하기 (0) | 2024.07.26 |
Swift 6.0 접근제어자 Access Control (0) | 2024.07.02 |