2007년 11월 27일
쓰레드와 쓰레드 동기화.
동시에 다양한 작업을 하기위해 멀티 프로세스 방식을 사용할수 있다.
멀티 프로세스 방식을 사용할때 많은수의 프로세스 생성은 빈번한 컨텍스트 스위칭(Context Switching)으로 이어져 성능에 부담을 준다.
쓰레드는 프로세스의 정보를 공유하기 때문에, 쓰레드 간에 컨텍스트 스위칭이 발생하더라도, 프로세스간 컨텍스트 스위칭보다 부담이 덜하다.
프로세스와 쓰레드의 차이점
쓰레드 특성
커널모드와 유저모드
프로세스가 유저모드에서 동작할때는 커널 영역으로 접근이 금지된다. 하지만, 커널모드에서 동작한다면 모든 영역의 접근이 허용된다.
커널레벨 쓰레드와 유저레벨 쓰레드
프로그래머의 요청에 따라 쓰레드를 생성 및 스케줄링 하는 주체가 커널인 경우, 이를 가리켜 커널레벨 쓰레드라 함.
커널에 의존적이지 않은 형태로 쓰레드의 기능을 제공하는 라이브러리를 활용하여 제공되는 형태의 쓰레드를 유저레벨 쓰레드라 함.
커널레벨 쓰레드와 유저레벨 쓰레드 차이.
유저레벨 쓰레드는 커널모드로 전환할 필요가 없기때문에 아주 약간의 성능상 이점이 있다.
커널레벨 쓰레드는 커널에서 직접 제공해 주기 때문에 안정성과 다양한 기능성이 제공됨.
유저모드에서 커널모드로 전환이 빈번하게 일어나기 때문에 성능 저하가 발생한다. (무시할만한 수준)
프로세스는 메인쓰레드(대표적으로 main함수)를 실행하고, 이 메인 쓰레드는 또 다른 쓰레드를 생성할수 있다. 기본적으로 쓰레드는 함수의 형태기 때문에[그림 필요] 쓰레드가 종료되었다는것은 함수가 종료되었다는것을 의미한다. 하지만 메인쓰레드는 함수의 종료가 아닌 프로세스의 종료를 의미하며, 메인쓰레드가 종료되면, 메인쓰레드에서 생성한 다른 쓰레드들도 종료된다.
쓰레드는 종료하는법.
쓰레드의 동시 접근 문제.
2개 이상의 쓰레드가 공유되고 있는 변수(ex> 전역 변수)에 접근시 순차적이지 않은 실행으로 인하여 예상한 값이 나오지 않는 경우가 있다. 우리가 흔히 쓰는 var++; 구문을 실행하는 중에도(어셈블리로 보면 3라인 정도의 실행문이 된다) 쓰레드 컨텍스트 스위칭은 빈번하게 일어난다. 때문에 둘 이상의 쓰레드가 같은 메모리 영역을 동시에 참조하는것은 문제를 일으킬수 있다.
쓰레드의 우선순위.
프로세스의 우선순위가 따로 있고, 쓰레드의 우선순위가 따로있다. 동일한 우선순위의 쓰레드라 하여도, 각각 우선순위가 다른 프로세스에서 실행된다면, 우선순위가 높은 프로세스에 포함된 쓰레드가 더 높은 우선권을 갇게 된다.
쓰레드의 동기화
쓰레드 동기화의 형태는 '메모리 접근 동기화'와 '(메모리 접근하는)실행 순서의 동기화'가 있다.
동기화의 두가지 유형
유저모드 동기화
PS. 이 내용은 윤성우 님의 저서 뇌를 자극하는 윈도우즈 시스템 프로그래밍을 요약한 내용입니다. : )
1. CRITICAL_SECTION의 LockCount와 RecursionCount, SpinCount가 뭘 의미하는지 모르겠음.
2. PEB에는 크리티컬 센션(구조체가) 하나 존재한다. 코드에서 크리티컬 섹션 객체를 2개 이상 생성하면 잘 작동하는가? 그 이유는?
3. 크리티컬 섹션 객체와 동일한 역할을 하는 뮤텍스가 존재하는 이유는 무엇인가? (유저영역 커널영역 차이 빼고..)
4. 크리티컬 섹션도 내부적(구조체)에 핸들을 가지고 있다. 이 말은 결국 크리티컬 섹션 객체도 커널영역에 직접 엑세스 한다는 의미가 아닌가?
5. 쓰레드가 리스트에 의해 라운드로빈 방식으로 실행된다면 어째서 쓰레드가 순차적으로 실행되지 못하는가?
::각 쓰레드 마다 퀀텀 시간을 지나면 하던 동작을 멈추고 다른 쓰레드에게 제어를 넘긴다. 만약 어떤 쓰레드가 다른 쓰레드 보다 더 오래 걸리는 작업을 다른 쓰레드와 동일한 퀀텀 시간에 작업을 한다고 하면, 당연히 결과가 늦게 나오며, 순차적으로 실행되지 않는듯이 보인다. (고 생각함.)
6. 이벤트 객체가 시그널 상태가 되면, 넌 시그널 상태가 되기 전까지 몇개의 쓰레드라도 임계영역에 진입할수 있는가? 아니면 한개의 쓰레드만 임계영역으로 접근 가능한가?
7. _try{} _finally{} 구문을 포함하는 쓰레드 프로시저를 exitThread(), terminateThread() 함수를 호출하여 쓰레드를 죽여버렸을 경우, _finally{}구문이 실행되는가?
::두 경우 모두 _finally{}이 실행 안됨.
멀티 프로세스 방식을 사용할때 많은수의 프로세스 생성은 빈번한 컨텍스트 스위칭(Context Switching)으로 이어져 성능에 부담을 준다.
쓰레드는 프로세스의 정보를 공유하기 때문에, 쓰레드 간에 컨텍스트 스위칭이 발생하더라도, 프로세스간 컨텍스트 스위칭보다 부담이 덜하다.
프로세스와 쓰레드의 차이점
- 쓰레드는 하나의 프로그램 내에서 여러 개의 실행 흐름을 두기 위한 모델
- 쓰레드는 프로세스처럼 완벽히 독립적인 구조가 아님. 쓰레드들 사이에는 프로세스의 정보를 공유.
- 쓰레드는 공유하는 요소가 있기 때문에 컨텍스트 스위칭에 걸리는 시간이 프로세스에 비해 짧음
쓰레드 특성
- 쓰레드별로 독립적으로 스택을 할당 받는다.
- 스택은 함수 호출시 전달되는 인자, 리턴 주소및 함수 내에 선언하는 변수등을 저장하기 위한 메모리 공간을 의미
- 코드 영역을 공유
- C(), ThreadA(), ThreadB()가 있을때, ThreadA()와 ThreadB()모두에서 C()를 호출할수 있다.
- 데이터 영역과 힙을 공유
- 코드 영역과 마찬가지. 단, 메모리 영역을 공유하다보면 메모리 관련 문제가 발생할수 있기때문에 프로그래밍시 주의해야함.
커널모드와 유저모드
프로세스가 유저모드에서 동작할때는 커널 영역으로 접근이 금지된다. 하지만, 커널모드에서 동작한다면 모든 영역의 접근이 허용된다.
커널레벨 쓰레드와 유저레벨 쓰레드
프로그래머의 요청에 따라 쓰레드를 생성 및 스케줄링 하는 주체가 커널인 경우, 이를 가리켜 커널레벨 쓰레드라 함.
커널에 의존적이지 않은 형태로 쓰레드의 기능을 제공하는 라이브러리를 활용하여 제공되는 형태의 쓰레드를 유저레벨 쓰레드라 함.
커널레벨 쓰레드와 유저레벨 쓰레드 차이.
유저레벨 쓰레드는 커널모드로 전환할 필요가 없기때문에 아주 약간의 성능상 이점이 있다.
커널레벨 쓰레드는 커널에서 직접 제공해 주기 때문에 안정성과 다양한 기능성이 제공됨.
유저모드에서 커널모드로 전환이 빈번하게 일어나기 때문에 성능 저하가 발생한다. (무시할만한 수준)
프로세스는 메인쓰레드(대표적으로 main함수)를 실행하고, 이 메인 쓰레드는 또 다른 쓰레드를 생성할수 있다. 기본적으로 쓰레드는 함수의 형태기 때문에[그림 필요] 쓰레드가 종료되었다는것은 함수가 종료되었다는것을 의미한다. 하지만 메인쓰레드는 함수의 종료가 아닌 프로세스의 종료를 의미하며, 메인쓰레드가 종료되면, 메인쓰레드에서 생성한 다른 쓰레드들도 종료된다.
쓰레드는 종료하는법.
- 쓰레드 프로시저(함수)에서 return문을 통해 쓰레드 종료
- ExitThread() 를 통한 쓰레드 종료
- 실행중인 쓰레드의 특정 위치에서 쓰레드를 종료시키려고 할때.
- TerminateThread() 를 통한 쓰레드 종료
- 쓰레드 생성시 얻은 핸들을 이용하여 쓰레드 외부에서 강제로 종료시키려고 할때.
쓰레드의 동시 접근 문제.
2개 이상의 쓰레드가 공유되고 있는 변수(ex> 전역 변수)에 접근시 순차적이지 않은 실행으로 인하여 예상한 값이 나오지 않는 경우가 있다. 우리가 흔히 쓰는 var++; 구문을 실행하는 중에도(어셈블리로 보면 3라인 정도의 실행문이 된다) 쓰레드 컨텍스트 스위칭은 빈번하게 일어난다. 때문에 둘 이상의 쓰레드가 같은 메모리 영역을 동시에 참조하는것은 문제를 일으킬수 있다.
쓰레드의 우선순위.
프로세스의 우선순위가 따로 있고, 쓰레드의 우선순위가 따로있다. 동일한 우선순위의 쓰레드라 하여도, 각각 우선순위가 다른 프로세스에서 실행된다면, 우선순위가 높은 프로세스에 포함된 쓰레드가 더 높은 우선권을 갇게 된다.
쓰레드의 동기화
쓰레드 동기화의 형태는 '메모리 접근 동기화'와 '(메모리 접근하는)실행 순서의 동기화'가 있다.
동기화의 두가지 유형
유저모드 동기화
- CRITICAL_SECTION 기반의 동기화
- 하나의 쓰레드만 들어갈수 있는 영역을 지정한다. (문 앞에 놓인 열쇠를 가진 사람만 문 안으로 들어갈수 있다.)
- Interlocked 함수 기반의 동기화
- MUTEX 기반의 동기화
- CRITICAL_SECTION과 다른게 무언가?
- SEMAPHORE 기반의 동기화
- 지정된 수의 쓰레드만 들어갈수 있는 영역을 지정한다. (문 앞에 한개 이상의 열쇠를 놓을수 있다.)
- Named MUTEX 및 Named SEMAPHORE 기반의 동기화
- 커널모드의 동기화 객체에 이름을 부여한다. 이름을 알고 있다면 누구나 사용 가능하다. (물론 사용하기 위해서는 열쇠가 필요하다.)
- EVENT 기반의 동기화
- 실행순서를 동기화 할때 사용.
PS. 이 내용은 윤성우 님의 저서 뇌를 자극하는 윈도우즈 시스템 프로그래밍을 요약한 내용입니다. : )
1. CRITICAL_SECTION의 LockCount와 RecursionCount, SpinCount가 뭘 의미하는지 모르겠음.
2. PEB에는 크리티컬 센션(구조체가) 하나 존재한다. 코드에서 크리티컬 섹션 객체를 2개 이상 생성하면 잘 작동하는가? 그 이유는?
3. 크리티컬 섹션 객체와 동일한 역할을 하는 뮤텍스가 존재하는 이유는 무엇인가? (유저영역 커널영역 차이 빼고..)
4. 크리티컬 섹션도 내부적(구조체)에 핸들을 가지고 있다. 이 말은 결국 크리티컬 섹션 객체도 커널영역에 직접 엑세스 한다는 의미가 아닌가?
5. 쓰레드가 리스트에 의해 라운드로빈 방식으로 실행된다면 어째서 쓰레드가 순차적으로 실행되지 못하는가?
::각 쓰레드 마다 퀀텀 시간을 지나면 하던 동작을 멈추고 다른 쓰레드에게 제어를 넘긴다. 만약 어떤 쓰레드가 다른 쓰레드 보다 더 오래 걸리는 작업을 다른 쓰레드와 동일한 퀀텀 시간에 작업을 한다고 하면, 당연히 결과가 늦게 나오며, 순차적으로 실행되지 않는듯이 보인다. (고 생각함.)
6. 이벤트 객체가 시그널 상태가 되면, 넌 시그널 상태가 되기 전까지 몇개의 쓰레드라도 임계영역에 진입할수 있는가? 아니면 한개의 쓰레드만 임계영역으로 접근 가능한가?
7. _try{} _finally{} 구문을 포함하는 쓰레드 프로시저를 exitThread(), terminateThread() 함수를 호출하여 쓰레드를 죽여버렸을 경우, _finally{}구문이 실행되는가?
::두 경우 모두 _finally{}이 실행 안됨.
이 글과 관련있는 글을 자동검색한 결과입니다 [?]
- Unix 와 Linux #1 by durian
- [low] 스레드 동기화 - 임계영역 by 시즈모드
- MAKE OS !!! by 미친감자
- [공부] Win API(Application Programming Interface)의 선지식 by 자코
- 리눅스 커널님에 대한 이해 by 미친감자
# by | 2007/11/27 19:18 | Study+more | 트랙백(1) | 덧글(2)






☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
제목 : 쓰레드와 쓰레드 동기화 II
쓰레드와 쓰레드 동기화. 이 전 시간에 해결하지 못한 질문들을 먼저 해결해 보도록 하자. 1. CRITICAL_SECTION의 LockCount와 RecursionCount, SpinCount가 뭘 의미하는지 모르겠음. 2. PEB에는 크리티컬 센션(구조체가) 하나 존재한다. 코드에서 크리티컬 섹션 객체를 2개 이상 생성하면 잘 작동하는가? 그 이유는? ::크리티컬 섹션 구조체 내부에는 디버그 구조체가 존재한다. 디버그 구조체 ......more