본문 바로가기
iOS/Swift

Swift) Main.sync 외 않됌?

by Jiseong 2022. 2. 13.

sync, async .. concurrent, serial을 공부하다가 main.sync를 돌려보니 프로그램이 죽는 것을 보고.. 왜 그런건지 어제 오늘 하루종일 생각해봤다.

왜 main.sync 하면 안됨?

먼저 생각해본 것은 뭐였냐면.. 

 

메인 스레드는 프로그램이 시작하고, 종료될 때까지 계속 일을 처리하고 있으니, 해당 스레드에 동기적으로 일을 시켜버리면 프로그램이 필수적으로 해야됐던 일을 내가 동기적으로 시킨 일을 처리할 때까지 하질 못하니깐 프로그램이 죽는거 아닐까? 라고 생각했다.

 

메인 큐는 serial queue이고, 일을 순차적으로 처리한다. 그리고 메인 큐는 일을 처리할 때 단일 스레드인 메인 스레드에 무조건 할당시키게되는데.. 이런 이유때문인가..? 도 했다..

 

그래서 내가 도달한 결론은 뭐냐!

 

코드를 작성할 때 별도의 처리를 하지 않았다면, 메인 스레드에서 작업을 한다.

DispatchQueue.main.sync {
    //task
}

자.. 위 코드는 메인 스레드에서 동작을 하게된다. 

 

코드로 드가보면 DispatchQueue.main.sync{}로 Task를 메인 큐로 보낸다

 

그럼 일단 메인 스레드에서 sync로 Task를 메인 큐로 보낸 것이니 메인 스레드는 Task가 끝날 때까지 기다리고 있을 것이다.

 

이유는.. 이거 포스팅 아직 안했는데 sync니깐 그렇다.

 

sync는 해당 작업에 대한 요청을 보내고 요청에 대한 응답이 올때까지 기다린다.

 

그니깐 작업 요청보내고 작업 끝날 때까지 아무것도 안한단거임

 

오로지 저 작업 완료만 기다린다! 사랑꾼이네

 

이 정도만 알고 다시 본론으로 가면 아까 "메인 스레드에서 sync로 Task를 메인 큐로 보낸 것이니 메인 스레드는 Task가 끝날 때까지 기다리고 있을 것이다." 라고 했다.

 

그림을 보자

현재 이 상태인거임 메인 스레드는 메인 큐로 Task를 보냈고 그 Task 완료될 때 까지 기다릴게~ 하고있음

 

그럼 이제 메인 큐에서 Task를 처리하기 위해 적합한 스레드로 보내게 되는데, 이 때 메인 큐는 serial 큐이기 때문에 순차적으로 Task를 메인 스레드(단일 스레드)에 할당한다.

Serial Queue는 단일 스레드에서 작업을 처리한다

그림을 보자!!!!!!!!!!!!

자.. 메인 큐는 메인 스레드한테 Task 처리해조!! 하면서 보낸다.

 

근데???? 아까 sync로 보냈다.

 

메인 스레드 입장에선 Task를 메인 큐에 보내고 Task 완료될 때까지 기다리고 있는데, 갑자기 일을 시키는거다.

쟤 Task 들고 뛰는거임 귀엽죠

메인 큐는 메인 스레드에 Task를 할당하여 Task를 시작해야 되는데, 메인 스레드는 Task가 처리되는 것을 기다리는 Block 상태이다. 

그럼 저 Task는 처리되지 못하고 메인 스레드에서 처리되길 기다리고 있는 Task가 처리돼 Block 상태가 풀릴 때까지 계에에에에에속 기다린다. 

 

근데 메인 스레드의 Block은 절대 풀리지 않는다.

 

왜? Task가 처리가 안됐으니깐!!!! 

 

이렇게 메인 스레드는 Task의 처리를 기다리고, 메인 큐는 메인 스레드가 기다리는 Task가 처리되서 Block이 풀리길 기다린다.

Block이 풀려야 Task를 메인 스레드에 할당하여 처리할 수 있기때문에!

 

기다림이 무한히 지속되어 프로그램이 런타임 오류를 내며 종료를 해버린다.

 

메인 스레드는 DeadLock이 되는 것이다. 절대 Block이 풀릴 일이 없다.

 

하지만 main.sync를 백그라운드 스레드에서 특별한 순서에 맞게 UI가 업데이트 되어야 할 때 사용할 수 있다.

DispatchQueue.global().async {
  // UI 업데이트 전 실행되어야만 하는 코드
  DispatchQueue.main.sync {
      // UI 업데이트
  }
  // UI 업데이트 후에 실행되어야만 하는 코드
}

무조건 못쓰는 건 아니란 것이다.

그럼 다른 serial 큐도 sync 안됨??

그럼 다른 serial 큐도 sync 안되느냐!, 걔도 단일 스레드이지 않느냐!!

 

아니다. 된다.

 

아니 뭐 이상하게 쓰면 안되는건 맞겠지

 

위에서 설명한 메인 큐는 메인 스레드 에 Task를 할당하여 작업을 처리한다.

 

근데 커스텀 큐(serial로 설정)는???? 

먼저 메인 스레드에서 커스텀 큐에 sync로 Task를 보낸다.

sync로 보냈으니 메인 스레드는 역시 Task가 완료될 때까지 기다리고 있겠지?

 

여기서부터 다르다.

 

커스텀 큐는 메인 큐처럼 메인 스레드에 Task를 할당하여 처리하는 것이 아닌 적합한 하나의 스레드에 Task를 할당하게 된다.

이렇게 적합한 스레드 하나에 Task 할당을 하니 데드락이 발생치 않는 것이다.

 

적합한 스레드에 할당된 Task가 완료되면~ 메인 스레드의 block 상태도 풀리고, 다른 스레드에서 처리하던 Task도 완료됐으니 스레드도 내려갈 것이다.

'iOS > Swift' 카테고리의 다른 글

Swift) Unit Test without networking  (0) 2022.02.20
Swift) GCD (Grand Central Dispatch)  (0) 2022.02.15
[Swift] 배열 안전하게 조회  (0) 2022.02.13
Swift) Subscript  (0) 2022.02.13
Swift) Dynamic Type, Accessibility Inspector  (0) 2022.02.13

댓글