📱 iOS/Swift

[Swift] Swift로 알아보는 동기-비동기 / 동시-직렬

kyxxn 2024. 7. 31. 00:44

공부한 개념

동기-비동기 / 동시-직렬

Serial 직렬

  • 작업을 다른 한 개의 스레드에서 처리
  • 직렬 큐에 담긴 작업은 오직 하나의 스레드에만 분배
  • 작업 시작과 종료가 예측이 가능
    → 순서가 중요한 작업을 처리할 때 사용
let concurrentQueue = DispatchQueue(label: "concurrentQueue", attributes: .concurrent)
// 동시성을 지원하는 큐

// 동기적으로 실행
concurrentQueue.sync {
    print("동기 작업 1 시작")
    sleep(2)  // 작업이 2초간 실행
    print("동기 작업 1 완료")
}

concurrentQueue.sync {
    print("동기 작업 2 시작")
    sleep(1)  // 작업이 1초간 실행
    print("동기 작업 2 완료")
}

print("모든 동기 작업 완료 후 실행")
// 실행결과
동기 작업 1 시작
동기 작업 1 완료
동기 작업 2 시작
동기 작업 2 완료
모든 동기 작업 완료 후 실행
  1. 위 코드는 DispatchQueue를 동시성을 지원하는 큐로 인스턴스를 만듬
  2. 그러나, sync로 동작하기 때문에 호출한 스레드, 즉 메인 쓰레드는 해당 작업이 끝날 때까지 기다리게 됨
  3. 즉, 2번 내용은 ‘직렬성’과 같음
  4. 동시성 큐를 이용해서 sync 작업을 하면 직렬성을 보장할 수 있음

Concurrent 동시

  • 작업을 다른 여러 개의 스레드에서 처리
  • 각 셀에서 이미지를 로드해야 한다면, 순서는 중요하지 않음
    → 빠른 게 장땡일 때 사용
let concurrentQueue = DispatchQueue(label: "concurrentQueue", attributes: .concurrent)
// 동시성을 지원하는 큐

// 비동기적으로 실행
concurrentQueue.async {
    print("비동기 작업 1 시작")
    sleep(2)
    print("비동기 작업 1 완료")
}

concurrentQueue.async {
    print("비동기 작업 2 시작")
    sleep(1)
    print("비동기 작업 2 완료")
}

print("모든 비동기 작업 추가완료")
// 실행결과
모든 비동기 작업 추가 완료
비동기 작업 1 시작
비동기 작업 2 시작
비동기 작업 2 완료
비동기 작업 1 완료
  1. 동시성을 지원하는 큐를 만듬
  2. async를 통해 작업을 여러 스레드로 보냄
  3. 호출한 스레드는 async, 즉 작업이 끝날 때까지 기다리지 않음
  4. 동시성 큐를 이용해서 async로 했으니, 메인 스레드의 print(”모든 비동기 작업 추가완료”)가 출력됨

직렬성을 지원하는 큐로 비동기적으로 실행한다면 ?

내가 헷갈렸던 부분

let serialQueue = DispatchQueue(label: "serialQueue")
// attrbutes: .concurrent 안 하면 직렬성을 지원하는 큐임

serialQueue.async {
    print("비동기 작업 1 시작")
    sleep(2)  // 작업이 2초간 실행
    print("비동기 작업 1 완료")
}

serialQueue.async {
    print("비동기 작업 2 시작")
    sleep(1)  // 작업이 1초간 실행
    print("비동기 작업 2 완료")
}

print("모든 비동기 작업 추가 완료")

위 코드 출력하면 뭐나올까 ? 어떻게 동작할까 ? 아래 정답있음 생각 ㄱㄱ

.

.

.

 

.

.

정답 코드 & 해설

// 실행결과
모든 비동기 작업 추가 완료
비동기 작업 1 시작
비동기 작업 1 완료
비동기 작업 2 시작
비동기 작업 2 완료
  1. 직렬성을 지원하는 큐는 하나의 스레드에만 작업을 보냄
  2. async를 했으면 호출한 메인스레드는 다음 작업을 할 수 있음
  3. 단, 작업을 할당받은 하나의 스레드는 작업이 끝날 때까지 기다림

동기-비동기 / 직렬-동시

동기와 비동기

  • 작업을 보낼 때, 호출한 스레드가 기다릴지 (= sync)
  • 혹은 호출한 스레드가 기다리지 않고 다음 코드를 실행할 지 (= async)

직렬과 동시

  • Queue로 보내진 작업을 하나의 스레드로 보낼지 (= Serial)
  • 혹은 여러 개의 스레드로 보낼 지 (= Concurrent)

DispatchQueue.global()

프로그램이 실행되면 만들어지는 하나의 DispatchQueue

  • 말 그대로 global()이므로, 전역에서 공유함
  • 동시성을 지원하는 큐임, Serial처럼 직렬적이지 못함
  • QoS를 통해서 우선순위 지정이 가능
  • 프로그램이 실행되면 스레드 풀을 통해 DispatchQueue가 할당할 스레드를 미리 만들어두고, 작업이 들어오면 놀고있는 스레드에게 작업을 할당
  • DispatchQueue.global().async는 비동기적으로 동작
    즉, 호출한 스레드는 작업이 끝나길 기다리지 않고 다른 동작을 함
  • DispatchQueue.global().sync는 동기적으로 동작함
    즉, 호출한 스레드는 작업이 끝날 때까지 기다림
    • 참고로 메인스레드에서 DispatchQueue.global().sync를 했다면, 해당 큐가 할당해주는 스레드는 메인 스레드이다.

레퍼런스

https://sujinnaljin.medium.com/ios-차근차근-시작하는-gcd-grand-dispatch-queue-1-397db16d0305

https://sujinnaljin.medium.com/ios-차근차근-시작하는-gcd-2-a65e1c28665d

https://sujinnaljin.medium.com/ios-차근차근-시작하는-gcd-3-1e706a74086b

https://sujinnaljin.medium.com/ios-차근차근-시작하는-gcd-4-a621eca0a1d2

https://sujinnaljin.medium.com/ios-차근차근-시작하는-gcd-5-c8e6eee3327b