프로세스 & 스레드
프로세스
프로그램을 메모리 상에서 실행중인 작업 (컴퓨터에서 실행중인 프로그램을 의미)
스레드
프로세스 안에서 실행되는 여러 흐름 단위
기본적으로 프로세스마다 최소 1개의 스레드 소유 (메인 스레드 포함)
프로세스는 각각 별도의 주소공간 할당 (독립적)
- Code : 코드 자체를 구성하는 메모리 영역(프로그램 명령)
- Data : 전역변수, 정적변수, 배열 등
- 초기화 된 데이터는 data 영역에 저장
- 초기화 되지 않은 데이터는 bss 영역에 저장
- Heap : 동적 할당 시 사용 (new(), malloc() 등)
- Stack : 지역변수, 매개변수, 리턴 값 (임시 메모리 영역)
스레드는 Stack만 따로 할당 받고 나머지 영역은 서로 공유
하나의 프로세스가 생성될 때, 기본적으로 하나의 스레드 같이 생성
프로세스는 자신만의 고유 공간과 자원을 할당받아 사용하는데 반해,
스레드는 다른 스레드와 공간, 자원을 공유하면서 사용하는 차이가 존재함
멀티프로세스
하나의 프로그램을 여러개의 프로세스로 구성하여 각 프로세스가 병렬적으로 작업을 수행하는 것
장점 :
1. 안전성 (메모리 침범 문제를 OS 차원에서 해결)
여러 자식 프로세스 중 하나가 죽어도 다른 프로세스에는 영향이 미치지 않아, 정상적으로 수행된다.
단점 :
1. 각각 독립된 메모리 영역을 갖고 있어, 작업량 많을 수록 오버헤드 발생. Context Switching으로 인한 성능 저하
멀티 스레드보다 많은 메모리 공간과 CPU 시간을 차지한다.
2. 프로세스간 복잡하고 어려운 통신기법
프로세스는 독립된 메모리영역 때문에 프로세스간 자원을 공유할 수 없고, 복잡하고 어려운 통신을 거쳐야 한다.
Context Switching
https://afteracademy.com/blog/what-is-context-switching-in-operating-system/
프로세스의 상태 정보를 저장하고 복원하는 일련의 과정
즉, 동작 중인 프로세스가 대기하면서 해당 프로세스의 상태를 보관하고,
대기하고 있던 다음 순번의 프로세스가 동작하면서 이전에 보관했던 프로세스 상태를 복구하는 과정을 말함
→ 프로세스는 각 독립된 메모리 영역을 할당받아 사용되므로,
캐시 메모리 초기화와 같은 무거운 작업이 진행되었을 때 오버헤드가 발생할 문제가 존재함
멀티 스레드
하나의 응용 프로그램에서 여러 스레드를 구성해 각 스레드가 하나의 작업을 처리하는 것
(비동기적이다 = 동시에 수행된다.)
- 동기(Synchronous)는 요청 후, 결과를 반환받은 후 작업 진행함.
- 비동기(Asynchronous)는 요청 후, 결과를 기다리지 않고 작업 진행함.
장점 :
1. 독립적인 프로세스에 비해 공유 메모리만큼의 시간, 자원 손실이 감소, context switch가 빠르다.
2. 스레드 간 통신에 별도의 자원을 이용하지 않고도, 전역변수 공간이나 heap 영역을 통해 데이터를 주고 받을 수 있다.
단점 :
1. 안전성 문제. 스레드간 자원을 공유하기 때문에, 하나의 스레드만 오류로 종료되어도 전체 스레드가 종료될 수 있다.
2. 동기화문제: critical section.
critical section
동일한 자원을 동시에 접근하는 작업을 실행하는 코드 영역이다.
스레드 간에는 전역 변수를 공유하므로 함께 사용할 때 충돌이 발생할 수 있다.
멀티 프로세스 대신 멀티 스레드를 이용하는 이유는?
1. 자원의 효율성 증대
2. 멀티스레드로 작업할 경우, 프로세스를 생성하여 자원을 할당하는 시스템콜이 줄어든다.
3. 프로세스간 context switch 시, CPU 레지스터뿐만 아니라 RAM과 CPU 사이의 캐쉬까지 초기화되어 오버헤드가 크기때문.
4. 스레드는 프로세스 내 메모리(stack 제외)를 공유하기 때문에 통신 비용이 적다.
5. 스레드 간 context switch 시, stack만 전환하면 되므로, 전환 속도가 빠르다.
유니티 코루틴(Coroutine)
https://docs.unity3d.com/kr/2021.3/Manual/Coroutines.html
단일 쓰레드로만 돌아가는 유니티에서 고안한 방법 중 하나로써, 이는 매 프레임마다 스케쥴링으로 관리가 됩니다.
매 프레임에서 IEnumerator의 반복기 형태로 호출되며 체크합니다.
Unity 코루틴이 시작되면 기본 Unity 스레드 내에서 한 번에 하나씩 실행되는 코루틴 대기열에 추가됩니다.
코루틴 내에서 양보 명령이 발생하면 코루틴이 일시 중지되고 별도의 대기열에 추가되며 기본 대기열의 다음 코루틴이 실행됩니다.
양보 조건이 충족되면 코루틴은 중단된 부분부터 재개되고 완료되거나 다른 양보 명령을 만날 때까지 계속 실행됩니다.
이 프로세스를 통해 메인 Unity 스레드 내에서 비차단 방식으로 코루틴을 실행하는 동시에 복잡한 동작과 애니메이션을 구현할 수 있습니다.
(비동기적이 아니다 = 동시에 수행되지 않는다.)
유니티 코루틴과 멀티 스레드의 차이점
Unity 코루틴과 멀티스레딩은 Unity에서 비동기 작업을 처리하기 위한 서로 다른 두 가지 접근 방식이며 몇 가지 중요한 차이점이 있습니다.
첫째, Unity 코루틴은 가볍고 Unity 엔진 자체에서 관리하는 반면 멀티스레딩은 운영 체제에서 관리합니다.
이는 코루틴이 멀티스레딩보다 리소스 집약도가 낮고 Unity 엔진에 더 쉽게 통합될 수 있음을 의미합니다.
둘째, 코루틴은 기본 Unity 스레드 내에서 작동하는 반면 멀티스레딩은 별도의 스레드에서 작동합니다.
즉, 코루틴은 일반적으로 특정 순서로 실행해야 하는 단기적이고 간단한 작업에 사용되는 반면
멀티스레딩은 병렬 처리가 필요한 더 복잡하고 오래 실행되는 작업에 사용됩니다.
또 다른 주요 차이점은 코루틴은 여전히 기본 Unity 스레드 내에서 실행되기 때문에 진정한 병렬 처리가 아니라는 것입니다.
즉, 코루틴은 진정한 병렬 처리 이점을 제공하지 않으며 여러 작업을 동시에 실행하는 데 사용할 수 없습니다.
반면 멀티스레딩은 각 스레드가 독립적인 작업을 동시에 실행할 수 있으므로 진정한 병렬 처리가 가능합니다.
이는 물리 계산, 오디오 처리 및 네트워크 통신과 같은 작업에 유용할 수 있습니다.
그러나 다중 스레딩은 경쟁 조건 및 기타 동시성 문제를 방지하기 위해 신중한 동기화가 필요하므로 관리하기가 더 어려울 수 있습니다.
다중 스레딩은 오류가 소스를 역추적하기가 더 어려울 수 있으므로 디버깅하기 더 어려울 수 있습니다.
요약하면 Unity 코루틴은 Unity 엔진 내에서 간단한 비동기 작업을 처리하는 가볍고 유연한 방법인 반면,
멀티스레딩은 병렬 처리가 필요한 더 복잡하고 오래 실행되는 작업에 사용됩니다.
Unity 코루틴은 기본 Unity 스레드 내에서 작동하며 진정한 병렬 처리 이점을 제공하지 않는 반면,
멀티스레딩은 진정한 병렬 처리를 허용하지만 관리 및 디버깅이 더 어려울 수 있습니다.
Unity Coroutine and multi-threading are two different approaches for handling asynchronous tasks in Unity, and they have some key differences. Firstly, Unity Coroutines are lightweight and managed by the Unity engine itself, while multi-threading is managed by the operating system. This means that coroutines are less resource-intensive than multi-threading, and can be more easily integrated into the Unity engine. Secondly, coroutines operate within the main Unity thread, while multi-threading operates in separate threads. This means that coroutines are typically used for short-lived and simple tasks that need to be executed in a specific order, while multi-threading is used for more complex and long-running tasks that require parallel processing. Another key difference is that coroutines are not true parallel processing, as they still execute within the main Unity thread. This means that coroutines do not provide true parallel processing benefits, and cannot be used to execute multiple tasks simultaneously. On the other hand, multi-threading allows for true parallel processing, as each thread can execute independent tasks simultaneously. This can be useful for tasks such as physics calculations, audio processing, and network communication. However, multi-threading can be more difficult to manage, as it requires careful synchronization to avoid race conditions and other concurrency issues. Multi-threading can also be more difficult to debug, as errors can be harder to trace back to their source. In summary, Unity Coroutines are a lightweight and flexible way to handle simple asynchronous tasks within the Unity engine, while multi-threading is used for more complex and long-running tasks that require parallel processing. Unity Coroutines operate within the main Unity thread and do not provide true parallel processing benefits, while multi-threading allows for true parallel processing but can be more difficult to manage and debug.