해당 포스팅은 iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해 강의를 수강하고 개인적으로 정리한 내용을 기록한 것 입니다.

디스패치 그룹의 개념


디스패치 그룹은 여러 작업을 유사한 기준으로 묶어 묶인 작업이 끝나는 시기가 필요할 떄 사용한다.

다음의 코드처럼 사용할 수 있다.

let group1 = DispatchGroup()
DispatchQueue.global(qos: ).async(group: group1) { } // 작업을 보낼 때 그룹 꼬리표를 붙여주는 느낌
DispatchQueue.global(qos: ).async(group: group1) { }
DispatchQueue.global().async(group: group1) { }

group1.notify(queue: DispatchQueue.main){ [weak self] in
	// 모든 작업이 끝났을 때 해당 클로저 실행
	self?.textLabel.text = "모든 작업이 완료되었습니다."
}


동기적인 기다림


어떤 이유로 그룹의 완료 알림에 비동기적으로 응답할 수 없는 경우, 대신 디스패치 그룹에서 wait() 메서드를 사용할 수 있다.
모든 작업이 완료될 때까지 현재 대기열을 차단하는 동기적인 방법으로,
작업이 완료될 때까지, 얼마나 오래 기다릴지 기다리는 시간을 지정하는 선택적 파라미터가 필요하다.
기다리는 시간을 지정하지 않으면 무제한 대기한다.

let group1 = DispatchGroup()
DispatchQueue.global(qos: ).async(group: group1) { }
DispatchQueue.global(qos: ).async(group: group1) { }
DispatchQueue.global().async(group: group1) { }

if group1.wait(timeout: .now()+60) == .timeOut {
	print("작업이 60초 안에 종료하지 않았습니다.")
}

작업이 제때 끝나지 않았을 때 처리하기 유용하다.


디스패치 그룹의 사용(비동기 디스패치 그룹)


디스패치 그룹 클로저 내에서 비동기 함수를 호출할 때 주의가 필요하다. 내부에서 비동기적으로 다른 메서드를 큐로 보냈기 때문에 종료 시점이 잘못 인식될 수 있다. 종료 시점을 명확히 표기하기 위해 enter(), leave() 메서드를 통한 출입처리가 필요하다.


queue.async(group: group1) {
	group1.enter() // 입장
	someAsyncMethod() {
		group1.leave() // 퇴장
	}
}




Dispatch workItem


  • 작업을 미리 정의해두고 사용하는 큐에 제출하기 위한 객체(class)
  • 빈약한 취소 기능, 순서 기능을 내장하고 있다.
let item1 = DispatchWorkItem(qos: .utility) {
	print("task1 출력")
}

let queue = DispatchQueue(label: "com.sbk.serial")
queue.async(execute: item1) // 객체이므로 따로 실행해줘야 한다.



빈약한 취소 기능

cancel() 내장 메서드를 갖고 있다.

  • 작업이 아직 시작되지 않은 경우 작업을 제거한다.
  • 작업이 실행중인 경우 isCancelled 속성이 true로 설정된다. (직접적으로 실행 중인 작업이 멈추는 것은 아니다.)

빈약한 순서 기능

notify(queue: 실행할 큐, execute: 디스패치 아이템) 내장 메서드를 갖고 있다.

  • 다음에 실행할 아이템(작업)을 지정


Semaphore


  • 공유 리소스에 접근 가능한 작업 수를 제한해야 할 경우 사용한다.
  • 한 번에 실행하는 작업의 갯수를 제한한다.
let semaphore = DispatchSemaphore(value: 3)
queue.async(group: group1) {
	group1.enter()
	semaphore.wait() // 일단 기다린다
	someAsyncMethod {
		group1.leave()
		semaphore.signal() //다음 작업 시작을 위한 시그널
	}
}

이미지 및 코드 참고: https://www.inflearn.com/course/iOS-Concurrency-GCD-Operation