기어가더라도 제대로

5. GCD 사용시 주의해야할 사항 본문

CS/동시성

5. GCD 사용시 주의해야할 사항

Damagucci-juice 2022. 9. 26. 21:01

반드시 메인큐에서 처리해야하는 작업

  • UI 관련일들은 "메인큐" 에서 처리해야한다.
  • 1번 스레드(메인 스레드) 는 계산 로직도 하지만, 화면 표시 작업도 담당한다.
    • 화면을 표시하는 일은 한개의 쓰레드(메인큐, 메인쓰레드)에서만 담당해야한다.
      • 1번 스레드에서도 화면을 업데이트하고
      • 2번 스레드에서도 화면을 업데이트한다면?
        • 그 작업이 같은 유아이작업을 했다면?
        • 운영체제는 어떤 쓰레드의 결정을 따라야하는가?

‏‏‎ ‎

  • 작업의 끝에 UI를 업데이트 해야하는 경우라면 그 부분만 main 큐에 보내야한다.

5. GCD 사용시 주의해야할 사항 image

‏‏‎ ‎

‏‏‎ ‎

5. GCD 사용시 주의해야할 사항 image

  • 다운로드 로직은 다른 큐에서 처리를 하고 이미지를 화면에 표시하는 작업은 Main 큐로 보내서 실행해야한다.
    • 하나의 작업 안에서 다른 큐로 작업을 보낼 수 있다.
  • urlSession의 dataTask 작업은 내부적으론 글로벌 큐에서 비동기적으로 처리된다.

5. GCD 사용시 주의해야할 사항 image

  • 예시와 같이 작업을 큐로 보내고, 그 안에서 또 다른 큐로 보내는 것이 가능하다.

‏‏‎ ‎

Sync 메서드에 대한 주의 사항

sync 와 관련해서 절대 해서는 안되는 2가지

5. GCD 사용시 주의해야할 사항 image

  1. 메인큐에서 다른 큐로 보낼 때 동기적으로 보내면 안된다.
    1. "메인큐에서는 항상 비동기적으로 보내야한다."
    2. 작업을 기다린다. 다른 스레드에 보낸 작업을 기다린다.
    3. 화면이 버벅거리는 현상이 발생한다.
      1. 메인에서 싱크로 보내면 다른 큐에서 실행되는 작업을 메인스레드가 기다리는 꼴이 된다.

5. GCD 사용시 주의해야할 사항 image

‏‏‎ ‎

  1. 현재의 큐에서 현재의 큐로 "동기적으로" 보내서는 안된다.
    1. 1번 작업을 비동기적으로 글로벌 큐(동시큐) 에 보냈는데
      1. 그림에서 task1 이 1번 스레드에 있다가 2번 스레드로 보냄
    2. 2번 쓰레드에 있는 1번 작업을 다시 동기적으로 현재의 글로벌 큐에 보내면
      1. 글로벌 큐는 동시 큐이므로 스레드 2번을 포함한 다른 스레드로 task1을 보낼 수 있음
        1. 근데 원래 보내는 큐가 직렬큐였다면?
        2. 2번 스레드에서 현재 스레드를 막고 지금해야하는 작업 task를 자기 자신의 스레드로 보내는 것임
        3. 이게 다름 아닌 데드락임

5. GCD 사용시 주의해야할 사항 image

이런 그림이 된다

5. GCD 사용시 주의해야할 사항 image

글로벌 큐는 동시큐니까 운이 좋아서 왔던 스레드로 다시 보내지 않고 다른 스레드로 보내면 데드락은 걸리지 않지만, 저렇게 선언하는 것 자체가 데드락의 가능성을 만들기 때문에 피해야하는 코드이다.

그치만 해당 큐를 sync 로 막아 놓고 다시 그 queue에 접근하는 모양새라 이런 실수는 잘 하지 않는다.

5. GCD 사용시 주의해야할 사항 image

이런 경우가 더 자주 있다. 데드락이 될 수도 있다.

  • 뷰 컨트롤러에서 글로벌 큐에 비동기적으로 작업을 보냈는데
  • 그 작업 내부의 객체에 접근할 때 글로벌 큐에 동기적으로 접근하는 경우가 있을 수 있다.
    • 해당 큐에서 해당큐로 작업을 동기적으로 보내는 상황과 동일
  • VC에서 보기엔 아무 문제 없는 코드가 실제로는 데드락을 발생시킬 수 있으므로 주의 해야한다.

weak, strong 캡처 주의

5. GCD 사용시 주의해야할 사항 image

  • 작업을 다른 큐로 보낸다고 할 때 그 작업은 클로저 형태로 다른 큐에서 실행된다.
  • 클로저로 작업을 할 때 객체에 대한 capture 현상을 주의해야한다.

5. GCD 사용시 주의해야할 사항 image

  • 객체 생성하면 ARC += 1
  • 다른 큐에 작업을 보낼 때
    • weak 캡쳐
      • ARC 변화 없음
      • 큐로 보낸 클로저(작업) 중단
    • strong 캡쳐
      • ARC += 1
      • 클로저(작업) 여전히 동작

‏‏‎ ‎

비동기 작업에서 컴플리션 핸들러의 존재 이유

  • 클로저 작업이 끝났음을 알림
  • 비동기 작업 처리를 하면
    • 작업이 오래걸릴 수 있음
    • 작업이 끝나는 시점을 알 필요가 있음
    • 여기가 컴플리션 핸들러가 있는 이유임

‏‏‎ ‎

동기 함수를 비동기 함수처럼 만드는 방법

  • 여러번 재활용하기 위해서 이렇게 한다.
  • 오래 걸리는 동기 함수를 비동기 적으로 어떻게 바꿀까?

5. GCD 사용시 주의해야할 사항 image

  • tiltShift(image:)
    • UIImage 편집 작업이라 오래 걸리고, 실험을 위해 1초간 잠들기 코드 있음, 한마디로 동기적인 함수임
  • 파라미터
    • 런큐
      • 작업을 수행할 큐
    • 컴플리션 큐
      • 작업이 끝났을 때 처리할 작업을 수행할 큐
    • 컴플리션 핸들러
      • 작업이 끝났을 때 처리할 작업을 정의
  • 동기적 작업을 비동기적으로 실행하기 위해, 작업을 실행할 큐와 작업을 완료 시킬 큐, 두가지 큐가 필요함
  • 5장의 이미지 처리를 한다고 가정하면
    • 동기적 처리의 소요시간
      • (1초 슬립 + 이미지 편집 시간) * 5
    • 비동기적 처리의 소요시간
      • 1초 슬립 + 5개의 이미지 중 가장 편집이 오래 걸리는 이미지의 소요시간

주의

URLSession과 같은 비동기 처리가 내장되어 있는 함수들은
개발자가 따로 operation, GCD 를 처리할 필요가 없다.(UI관련 작업은 필요)

‏‏‎ ‎

'CS > 동시성' 카테고리의 다른 글

7. Dispatch Group 개념  (0) 2022.09.26
6. weak self 관련  (0) 2022.09.26
4. 디스패치 큐의 종류  (0) 2022.09.26
3. 직렬과 동시  (0) 2022.08.31
2. 동기(Synchronous) VS Asynchronous(비동기)  (0) 2022.08.31
Comments