GCD에 관하여 - 2

2023. 3. 10. 19:37IOS

반응형

동기(Sync)

  • 동기란 하나의 작업(문맥)이 끝나기를 기다리는 것

  • 위와 같이 동기는 원두를 갈기 -> 컵 준비 -> 얼음 넣기의 각각의 작업이 실행 이후 끝난 다음 이후의 작업이 실행 된다.

비동기(Async)

  • 비동기란 이전 혹은 현재의 작업(문맥)이 끝나기를 기다리지 않고 바로 실행함
  • 비동기로 실행할 경우 먼저 실행 된 코드보다 이후에 실행 된 코드가 더 먼저 끝날 수도 있다.

  • 동기와는 다르게 실행 순서는 다르더라도 작업의 끝을 기다리지 않기 때문에 위와 같이 동작할 수 있다.
  • 다만, 여기서 원두 갈기 작업이 먼저 들어갔음에도 컵 준비, 얼음 넣기가 먼저 끝날 수도 있다.
  • 또한, 컵 준비 이후에 얼음을 넣어야 하는데 얼음 넣기가 먼저 끝날 수도 있기 때문에 순서가 필요할 경우 주의해야한다.

동시, 직렬, 동기, 비동기 정리

  • 동시, 직렬 - 쓰레드가 몇개인가에 따라서 다름(쓰레드가 하나면 직렬, 여러개면 동시)
  • 동기, 비동기 - 다음 작업이 언제 시작되느냐에 따라 다름(이전 작업이 끝나기를 기다리면 동기, 기다리지 않는 경우 비동기)

DispatchQueue

  • DispatchQueue | Apple Developer Documentation

  • 디스패치 큐란 작업에 대한 실행을 앱의 메인 쓰레드 혹은 백그라운드 쓰레드에서 직렬로 할지, 동시성으로 할지를 관리해주는 객체이다.

  • 해당 큐는 큐의 자료구조와 같이 FIFO 가장 먼저 들어온 작업이 가장 먼저 나가는 형태로 구현되어 있다.

  • 또한 쓰레드의 경우 시스템에서 관리해주는데 시스템에서는 메인쓰레드를 제외한 쓰레드가 최소 몇개를 할당한다는 것을 보장하지 않는다.

  • 즉 기기에 따라서 현재 자원의 상태에 따라서 시스템에서 적절하게 배분해준다.

  • 우리는 DispatchQueue를 사용할 경우 아래와 같은 두가지 항목을 필수로 생각해야한다.

    1. Concurrent(동시)인지, Serial(직렬)로 구현을 할 지 첫번째로 정해야한다.
    2. asyc(비동기), sync(동기) 이 중 어느것으로 작업을 구현 해야할지 정해야한다.

Concurrency Queue, Global Queue

  • global Queue는 메소드로 구현되어 있으며, 메소드 실행 시 동시성 큐이기 때문에 쓰레드를 추가로 생성한다.
DispatchQueue.global().async {
}

DispatchQueue.global().sync {
}

DispatchQueue(label: "labelText", attributes: .concurrent).async {
}

DispatchQueue(label: "labelText", attributes: .concurrent).sync {
}
  • DispatchQueue를 직접 생성 시 attributes를 주지 않으면 직렬성 프로그래밍으로 동작하므로 해당 인자에 concurrent를 주어 동시성 속성을 띄는 큐로 만들어야한다.

Serial Queue, Main Thread

  • Main 쓰레드의 경우 앱을 실행할 경우 코드 및 UI를 담당하는 쓰레드로 직렬 속성을 가지고 있다.
DispatchQueue.main.async {
}

//DispatchQueue.main.sync {        // Error
//}

DispatchQueue(label: "labelText").async {
}

DispatchQueue(label: "labelText").sync {
}

DispatchWorkItem

  • 기존 sync, async에 넣는 클로저, 코드블럭을 하나의 객체로 만들어 재사용 가능하도록 만들어주는 객체
let item = DispatchWorkItem {
    print("시작!!")
    sleep(3)
    print("끝")
}

asyncAfter

  • 특정 작업을 지정한 시간 이후에 비동기로 처리해준다.
func asyncAfter(
    deadline: DispatchTime,
    execute: DispatchWorkItem
)
  • deadline에서 해당 원하는 시간을 넣어주면 된다.
  • 다만, 특정 시간을 넣어줄 경우 async를 단순히 사용하는것 보다 덜 효율적이다.
  • DispatchTime의 경우 .now.distantFuture이 있는데 distantFuture을 사용하여 값을 특정해주는 것은 하지 말아야한다.
func asyncAfter(
    wallDeadline: DispatchWallTime,
    execute: DispatchWorkItem
)
  • wallDeadlinedeadline을 사용하는 두 버전이 있다.
  • 두 개의 차이는 시스템 즉 기기의 시간을 기준으로 하느냐 아니냐의 차이이다.

DispatchTime

A point in time relative to the default clock, with nanosecond precision
On Apple platforms, the default clock is based on the Mach absolute time unit.

  • 기본 시간 즉, 애플 기기의 시간에 따라 실행됨을 뜻한다.

DispatchWallTime

An absolute point in time according to the wall clock, with microsecond precision.

  • Wall Clock에 따른 시간을 의미하는데 Wall Clock은 CPU에서 코드를 실행하는데 있어서 사람이 볼 수 있도록 측정한 시간을 의미한다.
  • 즉, DispatchTime과는 다르게 코드 자체에의 실행시간을 의미한다.
DispatchQueue.global().asyncAfter(deadline: .now() + 5) {

}
DispatchQueue.global().asyncAfter(wallDeadline: .now() + 5) {
}
  • 만약 위와 같이 5초뒤에 실행하는 코드를 작성한다면 deadline을 사용할 경우 현재 기기의 시간 예를들어 7:30:00이라면 7:30:05일 때 실행될것이고
  • wallDeadline은 현재 코드가 실행되는 시간을 독립적으로 측정하여 해당 시간 5초 뒤에 실행을 시켜줄것이다.

asyncAndWait

  • 비동기 작업이 끝나기를 기다림으로 어떻게 보면 동기처럼? 작동을 할 수 있게 만들어주는 메소드이다.
반응형