• 카테고리

    질문 & 답변
  • 세부 분야

    모바일 앱 개발

  • 해결 여부

    미해결

안녕하세요, GCD 관련 질문드립니다..

23.11.02 11:24 작성 조회수 140

0

안녕하세요, 앨런,

 

Qos 부분을 수강하면서

수업 자료에 있던 코드들을 이렇게 바꾸어서 실행해보았는데요...

첫줄은 sync 라서 시작/완료까지 실행하고 task2, task4(비동기라서 완료까지 안 찍고 넘어가고), 그리고 task3 시작/완료 라고 이해를 했습니다. 제가 예상한 결과였고, 그렇게 출력이 되었어요.

근데 동일한 코드를 반복적으로 실행하면 그때마다 다른 결과가 나오는데.. 왜 그런지 모르겠어서 질문 남깁니다.. ㅠㅠ

어쩔때는 4가 먼저 실행되고

어쩔때는 3이 먼저 실행되더라구요..

왜 그렇게 순서가 바뀌는지가 가장 궁금하고..

qos를 통해서 우선순위를 설정한다는 의미가 언제 어떻게 우선순위대로 실행되도록 한다는 것인지 이해를 못 한 것 같습니다...

위 코드에서 userInteractiveQueue 가 defaultQueue.async(qos: .userInitiated)보다 우선순위가 높은 것이 실행을 먼저 하는 것은 아닌것 같은데.. 우선순위라는게 어떻게 반영이 되는것인지 감이 안 잡힙니다 ㅠㅠ

 

아니면 제가 쓸데없는 코드를 보면서 고민한건지.. 답변부탁드려요!!

답변 1

답변을 작성해보세요.

0

네 안녕하세요 syp0211 님!

작업(task1, task2, task3, task4)가 어떤 식으로 정의가 되어있을까요? 일반적으로.. 제가 보기엔 위와 같은 코드로 실험을 하는 것은.. 별로 의미가 없긴 합니다.

print 와 같은 코드로 출력을 하는 일은 CPU입장에서보면.. 엄청나게 빨리 끝낼 수 있는 일이고 (비동기로 일처리를 해야만 한다는 목적 하에서 오래 걸리는 일이 아니라는 뜻이고요.)

따라서.. 이렇게 짧은 일들은 거의 일이 배치가 되자마자 (GCD큐에 들어가자마자) 일의 실행까지 완료 시킬 수 있는 정도의 짧은 일이기 때문에.. 사실 이런.. print 코드로는 (큐의 배치나 우선 순위에 따른) 실험이 거의 불가 합니다.


그래서, 대략적으로 이런 일이 왜 발생하는지에 대해서 말씀드리면,
1번 작업은 sync이기 때문에.. (코드로 따지자면 67 ~ 68번째 줄에서) 다음 줄로 넘어가지 않고 1번작업이 완료 될때까지 기다리니까..
Task 1 시작
Task 1 완료 ★
이게 먼저 출력이 되는 것은 변함이 없는 사실이고요.

다만, 2, 3, 4번 작업의 순서는 언제든지 바뀌어도 이상하지 않습니다.
3번이 sync여도.. 2, 4번 작업은 일단 큐에 들어가니까.. (큐가 알아서 작업을 2, 3, 4번 쓰레드에 배치시키고 기다리지 않으니까) 작업을 시작 시키겠죠?

그렇기 때문에 이론적으로 보면 2, 3, 4번 작업은 정확한 순서를 우리가 보장할 수 없습니다. (2, 4번작업은 일단 큐에 배치되고 일이 시작 될 수도 있고 안될 수도 있고) 그렇기에 3번 작업과의 순서를 명확하게 따져볼 수 없다는 것이죠.

그러면, 여기서 또 한가지 의문이 드실 수도 있는데..
2번 작업의 우선순위는 userInitiated니까 2번 작업이 무조건 4번작업 보다는 빨라야 하는것 아니냐? 라고 생각하실 수도 있는데.. 그렇지 않습니다.

큐의 우선 순위라는 것은
제가 수업에서 그림으로 설명드린 것과 같이..
우선 순위 큐가 더 많은 쓰레드를 사용한다는 것이지 (그래서 일반적으로 빨리 일을 끝낼 수 있다는 개념에 가깝지) 무조건적으로 일을 빨리 끝낸다는 것은 아닙니다.
(pdf로 나누어 드린 그림을 다시 한번 확인해보셔요.)

따라서 우선 순위라는 개념에 따라서,
우선 순위가 높은 일이 무조건 일을 빨리 끝낼 수 있다는 것도 아닙니다. (어차피 여러개의 쓰레드가 동시적으로(Concurrent) 일을 하고 있기 때문에) 당연히 2번 작업과 4번 작업도 그 실행의 우선 순위를 명확하게 지정할 수 있는 개념이 아닙니다.

따라서 우선 순위라는 것은 이론적으로..
무조건적으로 해당되고 적용되는 개념이라기 보다는.. "일반적으로 지정해놓으면" 조금 빨리 끝낼 수 있으니, 필요에 따라 사용할 수도 있구나.. 라고 바라봐야하는 개념에 더 가까운 것 같습니다.

그리고 참고적으로 더 말씀드리면..
아무리 동일한 큐에 일을 배치시키면서 우선 순위를 지정하였다 하더라도..
여기서 정의하신 (print종류와 같이) 일이 배치가 되자마자 빨리 끝날 수 있는 정도의 일들이라면.. CPU는 배치되자마자 바로 끝내버릴 수 있는 정도의 짧은 일이기 때문에..
(큐에... 아직 안 끝난 수십개의 일들이 이미 쌓여있는 정도의 일이 아니라면..)
우선순위를 적용시켜서 실제 일을 빨리 일어나게 하는 정도의 실험은 어렵습니다...


위에 말씀드린 내용을 한번 이해해 보시고,
추가적으로 궁금하신 사항은 다시 질문주세요 ^^

감사합니다. :)

syp0211님의 프로필

syp0211

질문자

2023.11.02

설명듣고 왜 그런지 이해가 된 것 같아요! 답변 감사합니다!!

syp0211님의 프로필

syp0211

질문자

2023.11.02

호옥시 제가 이해한 바가 맞는지 ... 정리하고 싶어서 다시 답글 남깁니다..!!!

 

*DispatchQueue 자체가 원래 동시적을 내포하고 있어서, GCD를 사용하면 여러 쓰레드를 사용할 수 있음

 첫번째 task1의 sync 이거는 첫번째 작업이자 "동기"적인 작업이기 때문에 큐에 올리고, 그일을 쓰레드에서 처리하는 동안 완료될때까지 기다려야함 -> 그래서 얘는 무조건 첫번째 처리+완료될때까지 다른 코드들이 실행 안됨

두세번째의 task2와 task4는 async, 이거는 비동기이며 다른 우선순위.. 즉, 두개는 완료될때까지 메인 쓰레드에서 기다리지 않는데 두개 다 다른 쓰레드로 보내지게 됨, 언제 완료되는지 모름

마지막 작업의 task3의 sync 얘도 2.4거쳐서 바로 다른 메인이 아닌 다른 쓰레드의 동기 작업으로 올라감 이렇게 되어버리니까 1번째를 제외한 나머지는 다 각자 다른 쓰레드로 올라가서 어느게 먼저 실행되고 완료되는지 알 수 없기에 랜덤 결과 출력

 

라고 이해를 했는데 .... 맞을까요?! 제가 처음에 질문 드렸을때는 동시와 비동기를 헷갈려 하고 있던 것 같더라구요...!!

마지막 작업의 task4 라고 오타나신 것 같은데 (===> task3로만 바꾸시면 되고)
내용을 아주 정확하게 이해하셨습니다... ^^

syp0211님의 프로필

syp0211

질문자

2023.11.02

앗 오타.. 그렇네요.. ㅎㅎ 몇번을 봐도 헷갈리던게 이제 서서히 이해가네욥... ㅠㅠ 감사합니다!!!!!!!

화이팅!!!