Notice
Recent Posts
Recent Comments
Link
관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] DispatchQueue.main.sync 사용하면 deadlock 걸리는 이유 (sync, async, serial, concurrency 개념 이해하기) 본문

iOS 응용 (swift)

[iOS - swift] DispatchQueue.main.sync 사용하면 deadlock 걸리는 이유 (sync, async, serial, concurrency 개념 이해하기)

jake-kim 2023. 1. 2. 22:51

기본지식) sync, async, serial, concurrency

  • sync, async
    • sync - 해당 작업이 끝날때까지 대기
    • async - 대기하지 않음
      • 비동기가 필요한 이유? 대용량 이미지 파일 다운로드 시 기다리면 UI멈춘것처럼 보임
  • serial, concurrency
    • serial - 하나의 스레드로 처리
    • concurrency - 여러개의 스레드로 작업을 분산
      • 각각 독립적이지만 유사한 여러개의 작업을 처리하는 경우 (당근 마켓에서 반복적인 cell들의 물품 이미지 다운)
  • async vs concurrency 차이점?
    • async는 일의 시작 순서가 순서대로처리 하지 않음
    • concurrency는 일의 시작 순서는 차례대로 하지만 동시에 처리

DispatchQueue.main.sync 사용 주의 사항

  • deadlock 걸리는 케이스
    • main은 serial queue
    • A에서 serial queue 사용
    • B에서 serial queue를 sync로 진행한다는 의미: 지금 진행중인 queue에 print(123) 작업을 넣고 sync하게 처리하라는 의미
DispatchQueue.main.async { // A
	DispatchQueue.main.sync { // B
		print(123)
	}
}

// A
queue: [a1, a2, a3]

// B
queue: [a1, a2, a3, b1]
// b1을 sync로 처리? sync이므로 a1, a2, a3가 끝나고 나서야 b1 처리가 가능 
(근데 B가 들어오면서 main queue는 a1, a2, a3를 block한 상태이므로 b1을 처리하지 못하고 영원히 대기)

(만약 queue가 serial queue가 아닌 concurrent이면 멀티 스레드이므로 b1을 처리하는 스레드도 따로 있으므로 언젠간 b1이 끝나므로 deadlock x)

  • 주의: sync와 concurrent의 차이는?
    • conccurent + sync이면 일의 시작순서만 보장하고, 완료시간은 순서를 보장하지 않음
    • conccurent + async이면 일의 시작순서도 보장하지 않고, 완료시간도 순서를 보장하지 않음

deadlock 아닌 케이스

  • 내부가 sync가 아니면 ok
DispatchQueue.main.sync { // A
	DispatchQueue.main.async { // B
		print(123)
	}
}

// A
queue: [a1, a2, a3]

// B
queue: [a1, a2, a3, b1]
B를 만나면서 main queue 블락
b1을 async로 처리하라고 했으므로 a1, a2, a3가 끝나지 않아도 바로 처리가 가능 (끝난 후 다시 a1, a2, a3 실행)
  • concurrent queue이면 ok
    • global queue는 concurrent queue이므로 안전
let queue = DispatchQueue.global()
queue.sync {
	queuel.sync {
    	print(1)
    }
}

* cf) queue의 종류

  • main queue (serial queue)
    • DispatchQueue.main.queue
  • global queue (concurernt, qos 설정 가능)
    • DispatchQueue.global(qos: .default)
  • custom queue (디폴트는 serial이며 concurrent로 변경 가능)
    • DispatchQueue(label: "myQueue")
Comments