관리 메뉴

김종권의 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로 할당되어, 작업이 완료 될 때까지 쓰레드를 Block하여 점유 (하지만 스레드는 메인 스레드 한 개이므로 자기 자신을 블락한 것)

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

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

deadlock 아닌 케이스

  • 현재 main thread가 아니고 내부가 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