Grand Central Dispatch

나이든별 / Oldstar·2022년 6월 27일
0

Think about Keywords

목록 보기
33/37

공부한 것

  • GCD

고민한 점 및 생각해본 점

  • 먼저 되짚고 가자. 동시성 프로그래밍이란, 결국 동시에 하는 것처럼 보이게 하는 기술이다. 이걸 모르면 앞으로도 혼동이 올 수 있겠다고 생각했다.
  • GCD는 멀티스레딩을 쉽게 하기 위해 애플에서 제공하는 API이다. 멀티스레딩이 왜 필요한지는 일단 여기서는 다루지 않는다.
    • 쉽게 풀어 쓰자면, 나는 앱에게 시키고자 하는 작업을 DispatchQueue에 넣어 줄 뿐이다.
    • 애플은 이 큐에 있는 작업들을 QoS와 같은 여러 기준에 따라 알맞은 스레드에 분배한다.
  • DispatchQueue.main.sync는 안된다! 라는 한 마디에는 많은 것이 함축되어 있다.
    • Deadlock을 일으킬 수 있기 때문이다. 큐에 넣어준 작업이 끝날 때까지 기다리는데, 정작 큐는 멈춰 버리는 현상이라고 보여진다.
    • sync는 이전 작업이 끝난 다음 다음 작업을 시작한다는 의미를, async는 이전 작업을 먼저 시작할 뿐 끝나는 것을 기다리지 않고 다음 작업을 시작한다는 의미를 가진다.
    • 오잉 근데 serial queue는 한 번의 하나의 작업을, concurrent queue는 한 번에 여러 개의 작업을 할 수 있다고 그랬다.
    • 그렇다면 결국 serial + async는 의미가 없는 것이 아닌가?? 까지 생각이 확장됐다.

  • 이 고민을 해결하려면, 이전에 간과했던 몇 가지 부분을 들여다볼 필요가 있었다.
  • 먼저, 여러 개의 스레드를 이용한 프로그래밍을 하지 않는다면, 나는 GCD를 사용하고 있지 않은 것인가?
    • 아니오! 기본적으로 DispatchQueue.main 큐와 DispatchQueue.global 큐가 GCD의 기본값으로 지정되어 있다.
    • 특히, 메인 스레드는 UIApplication 싱글턴 객체와 main run loop, main event loop, UI 등 앱의 구동에 필수적인 것들이 올라간다.
    • 별도의 GCD 이니셜라이징 없이도 메인 큐가 이미 있는 이유는 또 위와 같은 경우 자주 사용되어서 그런 것이 아닐지.
  • DispatchQueue에 넣어준 작업만 작업이 아니다. 내가 쓰는 코드 한 줄 한 줄은, 전부 앱에서 수행해야 하는 작업이다.
  • 이제 데드락이 걸리는 조건을 확인해보자면...
@IBAction func deadlockSimulate() {
    print("1")
    DispatchQueue.main.sync {
        print("2")
    }
    print("3")
}
  • 예시 함수의 경우 IBAction 즉 UI와 관련된 함수이므로, 별도의 설정이 없다면 메인 스레드에서 돌아간다.
  • 큐에 작업이 들어가는 순서는, 우리가 코드를 읽는 순서와 같다. 위에서 아래로.
  • 먼저 1이 프린트된다. 다음으로 메인 큐에 2를 프린트하라는 명령을 넣는다.
  • 밑의 3을 프린트하고자 하는 명령은, 2를 프린트하는 메인 큐의 동기 명령이 완수되기를 기다린다.
  • 하지만, 2를 프린트하는 명령은 영원히 완료되지 못한다.
    • 3을 프린트하고자 하는 명령 또한 메인 큐이고, 이 큐는 메인 큐의 맨 끝에 넣어준 2를 프린트하는 명령이 완수되기를 기다리고 있기 때문! 이것이 데드락이다.
    • 이걸 왜 기다리고 있느냐? 어쨌든 2를 프린트하는 명령을 큐에 넣고 수행하는 코드는 3을 프린트하는 명령보다 윗줄에 있기 때문.
  • 이를 이해하기 위해 Source Queue와 Target Queue라는 개념을 통해 설명한 하단 글을 참조했다.
    • Source Queue는 Dispatch가 불러와진 곳. 이 곳에는 큐에 넣어주는 작업 말고도 수많은 다른 작업이 수행되고 있다.
    • Target Queue는 할 일을 받은 DispatchQueue.
  • 모든 코드는 작업이고, 이 작업은 GCD에 의해 큐에 넣어져서 수행된다. 우리가 큐를 불러올 때만 사용되는 것이 아니다.
  • 이제 각각의 큐의 속성이 serial한지 concurrent한지, 작업을 sync하게 넣어줄지 async하게 넣어줄지를 상황에 맞게 잘 결정해서 써 주면 되는 것이다.
  • (하지만 아직 좀 더 알아봐야 비로소 제대로 쓸 수 있을 것 같음)

참조

https://medium.com/@kkapilchoubisa/gcd-basics-serial-and-concurrent-queues-sync-vs-async-fdc3b22bbb3a

profile
함께 나아가고자 하는 사람

0개의 댓글