티스토리 뷰
Thread란 ?
하나의 프로세스내에서 실행되는 흐름의 단위. CPU이용의 기본 단위이기도 하다.

위와 같이 같은 프로세스에 속한 다른 스레드와 Code, Data, Heap, File등의 운영체제 자원들을 공유한다. 기본적으로 하나의 프로세스는 하나의 스레드로 동작하지만, 다수의 제어 스레드를 가진다면 동시에 하나 이상의 작업을 수행할 수 있다.
다중 Thread 프로그래밍의 장점.
1. 응답성(Responsiveness)
: 자원을 많이 사용하는 작업을 동작시켰을 때 단일 스레드 프로그램이라면 그 작업 이외에는 동작을
하지 못하게된다. 그러나 다중 Thread를 사용해서 자원을 많이 사용하는 작업을 Thread로 동작시킨
다면, 그 외의 작업도 문제없이 진행이 가능하다.
2. 자원 공유(Resource Sharing)
: 프로세스는 IPC를 통해서만 자원을 공유할 수 있다. 이러한 기법은 프로그래머에 의해 명시적으로 처리
되어야한다. 그러나 스레드는 자동적으로 그들이 속한 프로세스의 자원들과 메모리를 공유한다.
3. 경제성(Economy)
: 프로세스 생성을 위해 메모리와 자원을 할당하는 것은 비용이 많이든다. 물론 당연히 스레드에 비해서
오버헤드도 크다. 그래서 스레드를 이용하는것은 프로세스를 이용하는 것보다 경제적이다.
4. 규모 적응성(Scalability)
지금까지는 일반적 의미에서의 스레드를 다루었다. 그러나 스레드를 위한 자원은 User Threads를 위해서는 사용자 수준에서, Kernel Threads를 위해서는 커널 수준에서 제공된다. User Thread는 커널 위에서 지원되며 커널의 지원 없이 관리된다. 반면에 Kernel Thread는 운영체제에 의해 직접 지원되고 관리된다.
→ 솔직히 Kernel Thread라는게 직접 다뤄본적도없고 느낌이 와닿지는 않는듯 ;;
* User Thread가 Kernel Thread보다 오버헤드가 작고 속도측면에서 빠르다.
왜냐하면 커널의 관여가 없기 때문에 Context Switch가 없기 때문이다.
* User Thread
- Kernel에게 안보이는 Thread ( 속도↑. 빠르게 관리 )
(문제점)
1. Blocking System Call
- Blocking Function은 처리가 완료되지 않으면 Return되지 않는 함수들을 말한다. 예를들면 입력
함수들이 있다. 특정 Thread가 Blocking Function에 의해 Blocking상태가 되면, 프로세스전체가
Blocking이 된다. 하여 non-Blocking Function(System Call)만 사용해야 한다.
- 1:1 Model을 책택함으로써 해결했다. Kernel Thread가 늘어남에따라 속도저하의 가능성이 있어
Thread수의 제한을 둔다.
2. Shared System Rsource
- Synchronized나 Locking없이 공유자원 사용시 Overwrite가 발생할 수 있는 문제가 있다.
3. Signal Handling. Thread Scheduling.
4. Multi Process Utilzation.
User Thread와 Kernel Thread의 연관관계를 확립하는 방법.
1. Many-to-One Model ( N:1 )
Thread 관리는 사용자 공간의 스레드 라이브러리에 의해 행해진다. 따라서 매우 효율적이라고 할 수 있지만 한 Thread가 Blocking Function을 호출해 Blocking 상태가 된다면 프로세스 전체가 Blocking상태가 된다는 치명적인 단점이 존재한다. 또한 한 번에 하나의 Thread만 ㅋ널에 접근할 수 있기 때문에 다중 스레드가 다중코어 시스템에서 병렬로 실행될 수 없다.
이런 치명적인 문제점들 때문에 현재 이 모델을 사용하는 시스템은 거의 존재하지 않는다.
2. One-to-One Model ( 1:1 )
User Thread와 Kernel Thread를 각각 1대1로 매칭시킨다. 그러면 하나의 User-Thread가 Blocking Function을 사용하더라도 나머지 Thread가 정상적으로 실행될 수 있기 때문에 더 많은 병렬성을 제공한다.
그러나 이 모델의 하나의 단점은 User Thread를 생성할 때 다른 Kernel Thread를 생성해야 한다는 점이다. 이 때 발생하는 OverHead가 성능의 저하를 발생시키기 때문에 Thread 수 제한을 통해 보완하게된다. Windows, Linux 등등의 운영체제들이 해당 모델을 구현하고있다.
3. Many-to-Many Model ( N:M )
여러개의 User Thread를 그보다 작은 수 혹은 같은 수의 Kernel Thread로 MultiPlex하게 된다. Kernel Thread의 수는 응용 프로그램이나 특정 기계에따라서 결정된다. Solaris에서 사용했었지만 Solaris 9 부터는 One-to-One Model을 사용한다.
동기형 Threading VS 비동기형 Threading
- 비동기형 Threading : 부모는 자식Thread 생성 후 자기할일을 한다.
- 동기형 Threading : 부모는 자식Thread 생성 후 자식Thread의 종료를 기다린다.
( Fork - Join 전략 )
POSIX의 Pthreads.
- POSIX가 스레드 생성과 동기화를 위해 제정한 표준 API.
- Linux, Mac OS, Solaris등에 있지만 주로 Linux에서.. 라고 생각하자.
void* _________________(void* param);
→ 위와같은 모양의 Thread Function정의.
pthread_t tid;
→ Thread Identifier ( 앞으로의 Thread 관리는 이것을 통해서 한다. )
pthread_create(&tid, NULL, ___________, (void*)argument);
pthread_join(&tid, NULL); → 동기형 Thread
pthread_cancel(tid);
pthread_testcancel();
→ 밑의 두개의 함수를 통해서 생성한 Thread에 대한 취소요청이 가능하고,
해당 Thread에서는 자기가 취소요청이 됐는지 주기적으로 testcancel을 호출하게 된다.
- 기억해야 할 점은 반드시 gcc 컴파일시 -Pthread 옵션을 추가해줘야한다.
pthread_cleanup_push(void (*routine)(void*), void* args);
→ pthread_cleanup_pop 함수가 호출될 경우 첫 번째 매개변수로 전달해준 함수가 호출된다.
pthread_cleanup_pop(int num);
→ 인자는 0 또는 1이라고 생각하면되고, 1이면 실행 0이면 그냥 삭제이다.
pthread_cleanup_pop은 임의로 호출하지 않더라도 프로세스가 종료될 때 자동 호출된다.
WINDOWS API
- DWORD WINAPI ________(LPVOID Param);
- HANDLE ThreadHandle = CreateThread(
NULL,
0,
__________,
&Param,
0,
&Threadid); → DWORD Threadid로 Thread Identifier의 역할을 한다.
- WaitForSingleObject(ThreadHandle, INFINTE); → pthread의 join와 같은 역할.
- CloseHandle(ThreadHandle);
JAVA의 Thread, Runnable : 굳이 안해도될듯ㅎㅎㅎㅎ
openMP → C/C++ 병렬 프로그래밍
- 편하긴 진짜 편하다. 의외로 간단하니 자주 쓸지도..?
#include <omp.h>
#include <stdio.h>
int main(){
..................
#omp_set_num_threads(4); → 스레드 수 지정가능 (Default : 2개 !!)
#pragma omp parallel
{
이 내용에 대한것이 Thread로 동작한다.
omp_get_thread_num() 함수로 현재 동작중인 Thread의 번호 확인가능.
}
}
#pragma omp parallel for
for(int i=0; i<1000; ++i)
printf("%d\n", i);
와 같이 작성하면 이후에나오는 for문을 정해진 Thread수에의해 병렬처리하게된다.
#pargma omp critical 을 사용하게되면 이후 코드를 임계지역으로 지정하고,
경쟁상태에 놓이지않게 동기화과정을 거치게된다.
'운영체제(OS)' 카테고리의 다른 글
[OS] 다중 처리기 스케줄링 (0) | 2019.11.04 |
---|---|
[OS] CPU Scheduling 기본 ( 6가지 ) (0) | 2019.11.04 |
[OS] CPU Scheduling (0) | 2019.09.30 |
[OS] Process Synchronized (0) | 2019.09.07 |
[OS] IPC (Inter Process Communication) (0) | 2019.09.07 |