THIS IS ELLIE

DispatchSemaphore 클래스 본문

개발/iOS

DispatchSemaphore 클래스

Ellie Kim 2019. 8. 22. 20:04

디스패치 세마포어를 알아보기 전에 세마포어는 무엇일까요?

 

세마포어는 공유된 자원의 데이터를 여러 프로세스가 접근하는 것을 막는 것입니다.

뮤텍스는 공유된 자원의 데이터를 여러 쓰레드가 접근하는 것을 막는 것입니다.

또한 세마포어는 뮤텍스가 될 수 있습니다.

(그 반대는 불가합니다.)

 

이제 디스패치 프레임워크 내에 있는 디스패치 세마포어 클래스에 대해서 알아보겠습니다.

디스패치 세마포어를 사용하게 된 계기는 async한 작업을 sync하게 변경시켜보는 시도에 세마포어를 사용하면 어떨까 싶었고,

한 번도 사용해보지 못했던 클래스라 궁금했었기에 사용해봤습니다. 

 

그럼 애플에서 제공하는 공식문서를 살펴봅시다.

 

디스패치 세마포어란 다중 실행 콘텍스트에서 자원 접근을 제어하는 객체입니다. 

디스패치 세마포어는 전통적인 (counting semaphore) 카운팅 세마포어를 효율적으로 구현한 것입니다.

디스패치 세마포어는 호출 스레드가 차단돼야 할 때 커널을 호출합니다.

호출 세마포어를 차단할 필요가 없으면 커널 호출이 수행되지 않습니다.

 

디스패치 세마포어는 signal() 메소드를 이용해 세마포어 카운트를 증가시킬 수 있으며,

wait()나 타임아웃을 사용해 세마포어 카운트를 감소시킬 수 있습니다.

 

counting semaphore는 semaphore count가 0보다 작으면 실행되지 않으며, 0 이상이 되면 실행됩니다.

 


 

위 이미지 왼쪽을 보시면 도시들과 날씨가 나열되어 있습니다. 

이는 제가 추가한 도시 순서대로 테이블 뷰에 나열되어 있습니다.

 

하지만 앱을 다시 켰을 때 이슈가 발생합니다.

저장된 도시의 리스트를 가지고 있고 순서대로 Request를 날려 날씨를 받아오는 처리를 해주지만,

URLSession의 dataTask는 async하게 동작하고 여러개의 dataTask를 만들었을 때 여러개가 다 async하게 동작되기 때문에 

호출한 순서대로 도착하는 게 아니라 마음대로 도착하게 되겠죠. 

 

즉 이미지 오른쪽과 같이 도시들이 뒤죽 박죽으로 섞여버리게 됩니다.

 

이슈를 직면하고 async한 동작을 sync하게 처리해볼까 고민하고 dispatchSemaphore를 학습하고 사용하게 되었습니다.

 

(사실 추가한 순서대로 index를 부여하고 모든 것을 다 받아왔을 때 dispatchGroup.notify 내부에서 정렬을 해주어 테이블 뷰에 뿌려주는 방법도 있었지만 그래도 디스패치 세마포어 함 써보고 싶어서 써봄..ㅎ) 

 

 

DispatchSemaphore인스턴스를 만들고 task.resume() 아래에 semaphore.wait()를 작성해주었습니다.

그럼 코드가 쭉 실행됩니다.

 

순서를 살펴봅시다.

먼저 task.resume()아래 semaphore.wait()로 인해 semaphore count가 감소하게 되겠죠.

semaphore count가 0보다 작아지게 됩니다.

이로인해 스레드가 실행되지 않습니다. 

 

다음 dataTask내부 클로저 내부를 살펴봅시다.

즉 호출이 완료될 때 실행되는 곳에 semaphore.signal()을 작성해 semaphore count를 증가시켜줍니다.

이로 인해 semaphore count가 증가하게 됩니다.

이로인해 다시 스레드가 실행됩니다.

 

디스패치 세마포어를 사용한 전과 후를 print로그로 찍어보았습니다.

디스패치 세마포어를 사용해 하나의 task가 끝나면 다른 task가 실행되도록 sync하게 처리하여

추가된 도시 순서대로 도시에 대한 날씨를 받아올 수 있었습니다. 

 

하지만 디스패치 세마포어로 쓰레드 실행을 막는 것이기 때문에 네트워크가 불안정하거나 복잡한 구조에서 디스패치 세마포어를 사용하게 되면 deadlock의 위험도 존재하기 때문에 이 부분도 함께 고려해줘야 한다는 단점이 있었습니다.

 

https://developer.apple.com/documentation/dispatch/dispatchsemaphore