본문 바로가기

# 02/Swift

[Swift] DispatchQueue / Serial / Concurrent

반응형

DispatchQueue

작업 항목의 실행을 관리하는 클래스

애플리케이션에서 작업을 비동기 및 동시에 수행할 수 있게 해주는 GCD 대기열 위에 있는 추상화 계층

일반 스레드 보다 쉽고 효율적으로 코드를 작성할 수 있다. 보통 서버에서 데이터를 받고 이미지 동영상을 외부에서 다운로드 및 처리할 때 CPU 사용량이 많아 처리를 메인 스레드가 아닌 별도의 스레드에서 처리한 뒤 메인 스레드로 결과만을 전달하여 화면에 표시하도록 하여 CPU를 관리할 수 있다.

DispatchQueue 의 종류 - Serial / Concurrent

 

 

Serial Dispatch Queue - 비동기

이전 작업이 끝나면 다음 작업을 순차적으로 실행하는 직렬 형태의 큐.

하나의 작업을 실행하고 그 실행이 끝날 때까지 대기열에 있는 다른 작업을 잠시 미루고 있다가 직전의 작업이 끝나면 실행한다.

한 번에 하나의 작업만 수행합니다. 

직렬 대기열은 특정 값이나 리소스에 대한 액세스를 동기화하여 데이터 경합이 발생하지 않도록 하는 데 자주 사용됩니다.

 

let serialQueue = DispatchQueue(label: "swiftlee.serial.queue")

serialQueue.async {
    print("Task 1 started")
    // Do some work..
    print("Task 1 finished")
}
serialQueue.async {
    print("Task 2 started")
    // Do some work..
    print("Task 2 finished")
}

/*
Serial Queue prints:
Task 1 started
Task 1 finished
Task 2 started
Task 2 finished
*/

 

 

Concurrent Dispatch Queue - 동기

이전 작업이 끝날 때 까지 기다리지 않고 병렬 형태로 동시에 실행되는 큐.

즉 대기열에 있는 작업을 동시에 별도의 스레드를 사용하여 실행한다.

 

let concurrentQueue = DispatchQueue(label: "swiftlee.concurrent.queue", attributes: .concurrent)

concurrentQueue.async {
    print("Task 1 started")
    // Do some work..
    print("Task 1 finished")
}
concurrentQueue.async {
    print("Task 2 started")
    // Do some work..
    print("Task 2 finished")
}

/*
Concurrent Queue prints:
Task 1 started
Task 2 started
Task 1 finished
Task 2 finished
*/

 

 

경우에 따라서 데이터 경합을 방지하면서 동시에 여러 작업을 수행할 필요가 있다.

barrier flag 를 추가 하면 가능하다!

변수를 쓰기 전까지 읽기를 차단하는 방법이다.

 

final class Messenger {

    private var messages: [String] = []

    private var queue = DispatchQueue(label: "messages.queue", attributes: .concurrent)

    var lastMessage: String? {
        return queue.sync {
            messages.last
        }
    }

    func postMessage(_ newMessage: String) {
        queue.sync(flags: .barrier) {
            messages.append(newMessage)
        }
    }
}

let messenger = Messenger()
// Executed on Thread #1
messenger.postMessage("Hello SwiftLee!")
// Executed on Thread #2
print(messenger.lastMessage) // Prints: Hello SwiftLee!

 

 

 

Main Dispatch Queue 

메인 디스패치 큐는 애플리케이션의 메인 스레드에서 작업을 실행하는 전역적으로 사용 가능한 직렬 큐이다.

기본 스레드는 UI 업데이트에 사용되므로 이 대기열에서 작업을 실행할 때 의식하는 것이 중요합니다.

따라서 앞에서 설명한 디스패치 API를 사용하여 다른 스레드에서 작업을 수행하는 것이 좋습니다.

백그라운드 대기열에서 무거운 작업을 시작하고 완료되면 기본 대기열로 다시 파견할 수 있습니다.

 

let concurrentQueue = DispatchQueue(label: "swiftlee.concurrent.queue", attributes: .concurrent)

concurrentQueue.async {
    // Perform the data request and JSON decoding on the background queue.
    fetchData()

    DispatchQueue.main.async {
        /// Access and reload the UI back on the main queue.
        tableView.reloadData()
    }
}

유아이 작업은 메인 스레드 에서 해줘야 됨!

 

 

 

과도한 스레드 생성 방지

너무 많은 차단 작업이 concurrent dispatch queues에 추가되어 시스템에서 앱의 스레드가 부족해질 때까지 추가 스레드를 생성하는 경우 에는 문제가 될 수 있다.

global concurrent dispatch queues 를 사용해주면 너무 많은 추가 스레드를 방지할 수 있다.

QoS 를 통해 우선순위를 결정해 줄 수 있다. 우선순위가 높은 작업은 낮은 순위의 작업보다 더 빨리 실행되며, 이를 잘 적용하면 빠른 앱을 만들 수 있다.

 

DispatchQueue.global().async {
    /// Concurrently execute a task using the global concurrent queue. Also known as the background queue.
}

This global concurrent queue is also known as the background queue and used next to the DispatchQueue.main.

 

 

 

 


https://www.avanderlee.com/swift/concurrent-serial-dispatchqueue/

 

Concurrent vs Serial DispatchQueue: Concurrency in Swift explained

The differences between concurrent and serial dispatchqueue explained in Swift. How to use the main thread, background thread and prevent data races.

www.avanderlee.com

https://seons-dev.tistory.com/entry/Swift-DispatchQueue%EB%9E%80-GCD-Grand-Central-Dispatch

 

Swift : 기초문법 [DispatchQueue란?] (GCD : Grand Central Dispatch)

GCD 에 대해 알아보도록 합시다. DispatchQueue DispatchQueue는 작업 항목의 실행을 관리하는 클래스입니다. DispatchQueue는 장점은 일반 Thread 보다 쉽고 효율적으로 코드를 작성할 수 있습니다. 보통 서버

seons-dev.tistory.com

 

반응형

'# 02 > Swift' 카테고리의 다른 글

[Swift] 기초 입문 Study  (0) 2023.07.21
[Swift] RxSwift  (0) 2023.01.11
[Swift] DFS/BFS  (0) 2022.12.18
[Swift] MaxHeap  (0) 2022.12.12
[Swift] MinHeap  (0) 2022.12.12