Notice
Recent Posts
Recent Comments
Link
관리 메뉴

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

[iOS - swift] 2. 스레드 프로그래밍 이해하기 - Swift Concurrency가 나온 이유 (GCD의 한계, Thread explosion) 본문

iOS 응용 (swift)

[iOS - swift] 2. 스레드 프로그래밍 이해하기 - Swift Concurrency가 나온 이유 (GCD의 한계, Thread explosion)

jake-kim 2023. 2. 27. 22:43

1. 스레드 프로그래밍 이해하기 - 동시성 프로그래밍, thread, GCD, Swift Concurrency

2. 스레드 프로그래밍 이해하기 - Swift Concurrency가 나온 이유 (GCD의 한계, Thread explosion) < 

Thrad Explosion

  • Thread가 과도하게 만들어지게되어 비효율적이게 되는 현상을 의미
    • 저렴한 context switching 비용을 위해 thread를 만들었지만 아이러니하게도 8core에서 thread의 갯수가 100개가 되는 경우가 존재
    • 100개의 context switching보단 8개의 context switching이 효율적일것
    • 이 문제를 Thread explosion 라고 명칭
  • GCD는 Thread Explosion 문제가 존재하지만 새롭게 나온 Swift Concurrency의 actor는 thread를 재활용하며 thread의 갯수를 Core의 갯수와 동일하게 제한하여 이 문제를 해결

https://developer.apple.com/videos/play/wwdc2021/10254/

GCD가 Thread를 만드는 경우

  • sync는 thread를 재사용하고 async는 thread를 새로 생성
  • DispatchQueue.main 큐는 항상 동일한 thread를 사용하므로 custom queue를 얻어서 테스트
let myQueue = DispatchQueue(label: "myQueue")
  • 현재의 스레드를 출력하여 memory address가 다른지 보고 새로운 스레드인지 판단
    • custom queue에서의 스레드 한 개와 main queue에서의 스레드 한 개로 총 2개의 스레드가 있는 상태
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let myQueue = DispatchQueue(label: "myQueue")
        
        print(1, Thread.current)
        myQueue.async {
            print(2, Thread.current)
        }
        
        print(3, Thread.current)
        
        myQueue.async {
            print(4, Thread.current)
        }
        
        print(5, Thread.current)
        
//        1 <_NSMainThread: 0x6000037a42c0>{number = 1, name = main}
//        3 <_NSMainThread: 0x6000037a42c0>{number = 1, name = main}
//        5 <_NSMainThread: 0x6000037a42c0>{number = 1, name = main}
//        2 <NSThread: 0x6000037a0a80>{number = 6, name = (null)}
//        4 <NSThread: 0x6000037a0a80>{number = 6, name = (null)}
    }
}
  • myQueue는 serial queue이므로 attributes 파라미터에 .concurrent를 추가하여 테스트
    • 2, 4를 보면 스레드가 달라진 것을 확인
    • concurrent를 사용하면 thread가 많이 생성될 수 있음
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let myQueue = DispatchQueue(label: "myQueue")
        let someQueue = DispatchQueue(label: "someQueue", attributes: .concurrent)
        
        print(1, Thread.current)
        myQueue.async {
            someQueue.async {
                print(2, Thread.current)
            }
        }
        
        print(3, Thread.current)
        
        myQueue.async {
            someQueue.async {
                print(4, Thread.current)
            }
        }
        
        print(5, Thread.current)
        
//        1 <_NSMainThread: 0x600001b4c440>{number = 1, name = main}
//        3 <_NSMainThread: 0x600001b4c440>{number = 1, name = main}
//        5 <_NSMainThread: 0x600001b4c440>{number = 1, name = main}
//        4 <NSThread: 0x600001b00fc0>{number = 7, name = (null)}
//        2 <NSThread: 0x600001b0dd00>{number = 4, name = (null)}
    }
}
  • cf) swift에서 queue의 종류
    • DispatchQueue.main
    • DispatchQueue.global
    • custom queue - DispatchQueue(label:attributes:flags:)

정리

  • GCD는 Thread Explosion가 발생함
    • GCD 에서 sync를 활용하는 방법도 있지만 async를 쓰면 어쨌든 thread가 늘어나며 제한이 없어서 스레드가 많아지게 되면 성능 문제가 발생할 수 있음
  • Thread Explosion 문제를 해결한 Swift Concurrency가 나온 것
  • 스레드의 갯수를 core의 갯수와 동일하게 제한하는 Swift Concurrency를 사용하면 해결
  • 이 밖의 Swift Concurrency 장점은 기존의 call back을 처리하던 completion block 구조를 마지 sync 코드처럼 async - await를 이용하여 쉽게 처리할 수 있는 장점도 존재

 

(여기 https://velog.io/@enebin777/Swift-GCD-queue%EB%93%A4-%EA%B9%8A%EC%9D%B4-%EB%93%A4%EC%97%AC%EB%8B%A4%EB%B3%B4%EA%B8%B0

 

Comments