일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 프로세스 스케줄링
- 가상 메모리
- forEach
- 비동기
- Algorithm
- core data
- UserDefaults
- scrollview
- Swift
- Linked List
- IOS
- SwiftUI
- 데드락
- COLOR
- 동기화
- Apple Developer Academy
- decode
- 동시성
- 알고리즘
- async
- 100 days of SwiftUI
- struct
- Codable
- deadlock
- 오브젝트
- 인프런
- 운영체제
- 상호배제
- 앨런
- @state
Archives
- Today
- Total
기어가더라도 제대로
5. GCD 사용시 주의해야할 사항 본문
반드시 메인큐에서 처리해야하는 작업
- UI 관련일들은 "메인큐" 에서 처리해야한다.
- 1번 스레드(메인 스레드) 는 계산 로직도 하지만, 화면 표시 작업도 담당한다.
- 화면을 표시하는 일은 한개의 쓰레드(메인큐, 메인쓰레드)에서만 담당해야한다.
- 1번 스레드에서도 화면을 업데이트하고
- 2번 스레드에서도 화면을 업데이트한다면?
- 그 작업이 같은 유아이작업을 했다면?
- 운영체제는 어떤 쓰레드의 결정을 따라야하는가?
- 화면을 표시하는 일은 한개의 쓰레드(메인큐, 메인쓰레드)에서만 담당해야한다.
- 작업의 끝에 UI를 업데이트 해야하는 경우라면 그 부분만 main 큐에 보내야한다.
- 다운로드 로직은 다른 큐에서 처리를 하고 이미지를 화면에 표시하는 작업은 Main 큐로 보내서 실행해야한다.
- 하나의 작업 안에서 다른 큐로 작업을 보낼 수 있다.
- urlSession의 dataTask 작업은 내부적으론 글로벌 큐에서 비동기적으로 처리된다.
- 예시와 같이 작업을 큐로 보내고, 그 안에서 또 다른 큐로 보내는 것이 가능하다.
Sync 메서드에 대한 주의 사항
sync 와 관련해서 절대 해서는 안되는 2가지
- 메인큐에서 다른 큐로 보낼 때 동기적으로 보내면 안된다.
- "메인큐에서는 항상 비동기적으로 보내야한다."
- 작업을 기다린다. 다른 스레드에 보낸 작업을 기다린다.
- 화면이 버벅거리는 현상이 발생한다.
- 메인에서 싱크로 보내면 다른 큐에서 실행되는 작업을 메인스레드가 기다리는 꼴이 된다.
- 현재의 큐에서 현재의 큐로 "동기적으로" 보내서는 안된다.
- 1번 작업을 비동기적으로 글로벌 큐(동시큐) 에 보냈는데
- 그림에서 task1 이 1번 스레드에 있다가 2번 스레드로 보냄
- 2번 쓰레드에 있는 1번 작업을 다시 동기적으로 현재의 글로벌 큐에 보내면
- 글로벌 큐는 동시 큐이므로 스레드 2번을 포함한 다른 스레드로 task1을 보낼 수 있음
- 근데 원래 보내는 큐가 직렬큐였다면?
- 2번 스레드에서 현재 스레드를 막고 지금해야하는 작업 task를 자기 자신의 스레드로 보내는 것임
- 이게 다름 아닌 데드락임
- 글로벌 큐는 동시 큐이므로 스레드 2번을 포함한 다른 스레드로 task1을 보낼 수 있음
- 1번 작업을 비동기적으로 글로벌 큐(동시큐) 에 보냈는데
이런 그림이 된다
글로벌 큐는 동시큐니까 운이 좋아서 왔던 스레드로 다시 보내지 않고 다른 스레드로 보내면 데드락은 걸리지 않지만, 저렇게 선언하는 것 자체가 데드락의 가능성을 만들기 때문에 피해야하는 코드이다.
그치만 해당 큐를 sync 로 막아 놓고 다시 그 queue에 접근하는 모양새라 이런 실수는 잘 하지 않는다.
이런 경우가 더 자주 있다. 데드락이 될 수도 있다.
- 뷰 컨트롤러에서 글로벌 큐에 비동기적으로 작업을 보냈는데
- 그 작업 내부의 객체에 접근할 때 글로벌 큐에 동기적으로 접근하는 경우가 있을 수 있다.
- 해당 큐에서 해당큐로 작업을 동기적으로 보내는 상황과 동일
- VC에서 보기엔 아무 문제 없는 코드가 실제로는 데드락을 발생시킬 수 있으므로 주의 해야한다.
weak, strong 캡처 주의
- 작업을 다른 큐로 보낸다고 할 때 그 작업은 클로저 형태로 다른 큐에서 실행된다.
- 클로저로 작업을 할 때 객체에 대한 capture 현상을 주의해야한다.
- 객체 생성하면 ARC += 1
- 다른 큐에 작업을 보낼 때
- weak 캡쳐
- ARC 변화 없음
- 큐로 보낸 클로저(작업) 중단
- strong 캡쳐
- ARC += 1
- 클로저(작업) 여전히 동작
- weak 캡쳐
비동기 작업에서 컴플리션 핸들러의 존재 이유
- 클로저 작업이 끝났음을 알림
- 비동기 작업 처리를 하면
- 작업이 오래걸릴 수 있음
- 작업이 끝나는 시점을 알 필요가 있음
- 여기가 컴플리션 핸들러가 있는 이유임
동기 함수를 비동기 함수처럼 만드는 방법
- 여러번 재활용하기 위해서 이렇게 한다.
- 오래 걸리는 동기 함수를 비동기 적으로 어떻게 바꿀까?
- 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