맛동산이

Swift) Swift concurrency가 나온 배경에 대해서, thread와 GCD의 한계점 본문

앱/Swift

Swift) Swift concurrency가 나온 배경에 대해서, thread와 GCD의 한계점

진ddang 2023. 8. 28. 15:13

이전에도 다양하게 다룬적이 있지만 이제야 좀 정리가 되는느낌이라 다시한번 정리하려고 합니다.


Thread

스레드는 cpu에서 바라보는 작업단위이다.

프로그램은 저장소에 저장되어있는 코드 덩어리이고, 이 코드덩어리가 메모리에 올라간 상태를 프로세스라고 한다. 프로세스는 cpu가 할당되어진 프로그램의 상태인것

프로세스 내부에서 동시성(time slicing)방식으로 여러개의 일을 처리할수 있는데, 이때 생성되는 독자적인 프로세스 내부의 작업 단위를 스레드라고한다.

ex) 크롬이라는 프로그램이 메모리에 올라가면 프로세스, 해당 크롬에서 여러개의 창이 켜진상태를 여러 스레드가 존재한다고 생각하면 쉽다.

Thread pool

위의 스레드 생성방식에서 계속해서 새로운 스레드를 생성하는것은 좀 불필요한 작업일수 있기 때문에

기존에 여러개의 스레드들 미리 생성해두고 그것을 재사용하는 방식을 의미하며

이때 이미 생성되어있는 스레드를 스레드 풀이라고 한다.

문제점

스레드는 코드에서 여러곳에서 명시적으로 생성해서 사용하는데 관리가 어려워 지며, 스레드 explosion이 생길 가능성이 존재한다.

스레드는 non -blocking 방식을 지원하지 않기 때문에 그렇다. (스레드는 다른 스레드에 의해서 blocking이 되지 않는다는 뜻이다, 자신의 역할이 정해졌을때, 다른 역할에 관계없이 작업이 진행되지 않는다는 뜻)

즉 무한정으로 스레드가 생성되면, 이는 스레드들이 계속해서 서로 cpu를 가져가기 위해서 경쟁상태(교착)이 일어날수 있기 때문이다.

GCD(grand central dispatch)

GCD는 큐를 사용해서 Thread를 관리하게 된다.

Dispatchqueue라는 큐를 사용해서 스레드를 생성 관리하게 되며, (큐 안에서는 하나의 스레드에서 처리하게 된다.)

Dispatchqueue는 non-blocking을 제공하고 있기 때문에 여러 작업이 동시적으로 돌아갈수 있다.

이처럼 스레드풀을 관리하기 위해서 만들어진게 바로 GCD이다.

  • 하지만 여전히 명시적으로 스레드를 무한정 생성할수 있으며~~(그러지는 않겠지만)~~
  • 여전히 data race에 관한 위험이 남아있다.
  • 한개의 큐에서 정말 오랜시간이 걸리는 작업이 발생한다면?
  • 또한 Task가 여러 Thread를 옮겨다니게 되면 Thread가 계속 늘어나게(팽창) 됩니다. (여전한 explosion의 위험)

예를 들어서

func explodingCPU() { 	let queue = DispatchQueue(label: "explosion!", attributes: .concurrent)  	for n in 0..<1000 { 		queue.async { 			print(Thread.current) 			while true { } 		} 	} } 

이 여러 작업이 한번에 일어나게 되면, 하나의 스레드에서는 엄청난 부하가 걸리게 되고, concurrent하게 작업이 실행되기 때문에 cpu의 한계로 인해서 다른작업들이 실행될수 없게 된다.

Untitled.png

실제로 돌려보면 일정 코어수 이상으로는 스레드가 돌아가지 않는다.

이러한 문제를 해결하기 위해서 Swift concurrecy가 생겼다.

반응형