• 카테고리

    질문 & 답변
  • 세부 분야

    모바일 앱 개발

  • 해결 여부

    미해결

강의 11분 36초에서 질문입니다.

21.07.18 18:23 작성 조회수 126

1

안녕하세요.

"main.sync는 절대 사용하면 안된다"라는 부분에서 질문입니다.

1. main큐(serial큐)는 유일하게 UI작업을 처리할 수 있는 큐고 특별히 os는 UI작업을 위해서 이 main큐에서 1번쓰레드로만 작업을 보낸다고 이해하고 있습니다. 제대로 이해하고 있는게 맞나요?

2. 

1번쓰레드에서 작동하는 코드에서(예를들면 TableView의 cellForRowAt메서드),

메인큐로 main.sync 작업을 추가하는 코드를 작성했다면,

os는 이 작업은 main큐에 있던 것이므로 1번 쓰레드로 작업을 보내면서 동시에 sync작업이기때문에 1번쓰레드를 block시켜서 교착상태를 만들어 내는건가요?

3. 

11분36초(메인큐에서는 다른큐로 보낼때 sync메서드를 부르면 안된다의 설명 부분)에 나오는 그림은 Thread1에서 Thread2로 작업이 들어가는데 Thread1의 맨 앞에서 Thread1의 맨 뒤로 task1이 들어가는 그림이어야 하는게 아닌가요?

답변 1

답변을 작성해보세요.

0

네! 안녕하세요 mi kim 님 ^^

1.번 질문에 대한 답변

네 제대로 이해하신 것이 맞습니다. "main큐는 항상 작업을 1번쓰레드라고 보낸다"라고 이해하셔도 되고, "main큐 자체가 1번 쓰레드와 동일하다"라고 이해하셔도 됩니다. 결국 본질은 동일하기 때문이예요.

그리고 예를 들어 아래와 같은 일반적인 코드는
(우리가 다른 큐로 보내지 않는한) 무조건 메인큐로 보내집니다.

print("작업1")
print("작업2")

이라는 코드를 친다면 그냥 메인쓰레드(메인큐)로 배치가 됩니다. 

즉, 어떻게 보면 사실은..

DispatchQueue.main.sync {
print("작업1")
print("작업2")
}

이런 제가 빨간색 글씨로 입력한 코드가 우리 눈에 안보이지만 숨어있다고 생각하시면 됩니다.

그래서.. 그렇기 때문에, DispatchQueue.main.sync를 사용하면 안된다 라고 말씀을 드리는 겁니다.

예를 들어 아래처럼

DispatchQueue.main.sync {
print("작업1")
             DispatchQueue.main.sync {
                            print("작업2")
             }
}

이런일이 일어난다면 어떻게 될까요? 현재의 큐에서 현재의 큐로 sync로 보내면 (절대) 안된다고 말씀을 드렸는데.. 잘 보시면 원래 작업을 하고 있던 1번 쓰레드에서 print("작업2") 작업을 sync로 보냈으니 기다릴께 했는데.. 다시 1번 쓰레드에 배치가 되어서.. 데드락(DeadLock)의 상태가 되는 겁니다. 즉, 일이 진행이 안되는 상태가 되어 버리기 때문에.. main.sync는 사용하면 안된다고 말씀을 드린겁니다.




2.번 질문에 대한 답변

네,  만약에 상황처럼 말씀하신 것이면 정확하게 맞습니다. 1번쓰레드에서 다시 1번쓰레드로 기다릴꺼야 라고 보내니..  block의 상황이 일어나 데드락이 일어나는게 맞습니다.

그런데 일반적으로는 cellForRowAt메서드 내에서는 비동기처리(URLSession등 네트워킹 작업)를 하는 것이 일반적이니 작업을 끝내고, (즉, 2번쓰레드 등에서 하던일을) 다시 그냥 비동기적으로 main.async(비동기적)로 보내는 것이죠.
(비동기 작업 내에서 main.sync로 보낼 일도 당연히 없습니다. 그건.. 음.. 너(main쓰레드)가 그림을 그리는 것을 끝낼때까지 내가(2번) 기다릴께 라는 말인데.. 2번쓰레드는 당연히 그림그리는 일과 전혀 무관하게 할일만 하면 되는 것이므로 UI작업을 위해서 main.sync를 쓸일은 없고, main.async으로 사용하는 것입니다.)



3.번 질문에 대한 답변

제가 mi kim님께서 질문주신 의도를 잘 파악하지 못하겠는데..

DispatchQueue.global( ).sync {

             print("작업1")

}    // 1번 쓰레드는 글로벌큐로 보내도 계속 여기서 기다림

print("작업2")

print("작업3")

print("작업4")

제가 의도한 코드는 더 정확하게 표현하자면 이런 내용이고, 글로벌 큐로 보내도 sync로 기다린다고 하였으니, 이런 경우에는 print가 순서대로 일어납니다. ^^

혹시 의도하신 내용이 이런 내용이 아니셨다면 질문 다시 주세요!



제 강의를 수강해 주셔서 감사드리고, 

열심히 공부하고 계시니 또 질문 올려주시면 열심히 답변드릴께요 :)



고맙습니다. :)