일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 홍대 방탈출
- 공포 방탈출
- C 자료구조
- Unity
- 추천
- 방탈출
- 필활
- PC VR
- C#
- 2021 방탈출 추천
- 윈도우 프로그래밍
- 유니티
- 넥스트에디션 2호점
- 홍대 덤앤더머
- 강남 방탈출
- 홍대 방탈출 추천
- 꽃길
- 방탈출 추천
- 개발
- 넥스트에디션
- 후기
- 정렬 알고리즘
- 시스템 프로그래밍
- Android
- 이스케이퍼스 2호점
- C++ 자료구조
- 이스케이퍼스
- 방탈출 리뷰
- 홍대
- 방탈출 후기
- Today
- Total
행복한 연어의 이야기
(윈도우 시스템) 13. 쓰레드 동기화 기법 1 (메모리 접근에 대한 동기화) 본문
1. 쓰레드 동기화란 무엇인가?
두가지 관점에서의 쓰레드 동기화
실행순서의 동기화
쓰레드의 실행순서를 정의하고, 이 순서에 반드시 따르도록 하는 것
메모리 접근에 대한 동기화
메모리 접근에 있어서 동시 접근을 막는 것
쓰레드 동기화에 있어서의 두 가지 방법
유저모드 동기화
커널 코드가 실행되지 않는 동기화 기법
성능상의 이점이 있지만 기능상의 제한이 있다.
커널모드 동기화
커널에서 제공하는 동기화 기능을 활용하는 방법
관련 함수가 호출할때마다 커널모드로 전환이 되어 성능 저하로 이어지만
다양한 기능을 제공을 받을 수 있다.
2. 임계 영역(Critical Section) 접근 동기화 (메모리 접근에 대한 동기화)
임계영역에 대한 이해
메모리 접근에 있어서 동기화와 관련된 내용이다.
임계 영역이란 한순간에 하나의 쓰레드만 접근이 요구되는 코드 블록을 의미한다,
즉 둘이상의 쓰레드가 동시에 실행하면 문제가 발생하는 프로그램상의 코드 일부를 뜻한다.
동기화 기법을 통해 임계영역은 한순간에 하나의 쓰레드만 접근하게 해야한다.
3. 유저 모드의 동기화
크리티컬 섹션 기반의 동기화 (유저 모드 동기화)
크리티컬 센션 기반의 동기화는 크리티컬 변수를 선언, 초기화 후
크리티컬 섹션 관련 함수를 통해 임계 지점의 시작 과 끝을 감싸
함수 사이 부분은 한 쓰레드만 접근 할 수 있게 제한하는 기법이다.
CRITICAL_SECTION CriticalSection; //크리티컬 섹션 변수 선언
void InitializeCriticalSection( //변수 초기화 함수
LPCRITICAL_SECTION lpCriticalSection //선언한 변수를 초기화 해주어야 사용가능
);
void EnterCriticalSection( //임계 영역 전 호출
LPCRITICAL_SECTION lpCriticalSection //초기화한 변수 넣어줌
);
void LeaveCriticalSection( //임계 영역 끝난 후 호출
LPCRITICAL_SECTION lpCriticalSection //초기화한 변수 넣어줌
);
void DeleteCriticalSection( //변수 초기화과정에서 할당된 리소스 반환
LPCRITICAL_SECTION lpCriticalSection //초기화한 변수 넣어줌
);
//============================================= 아래는 진행 순서
CRITICAL_SECTION 변수 선언
InitializeCriticalSection 함수 호출로 변수 초기화
EnterCriticalSection 함수 호출로 시작 지점 지정
//임계 영역//
LeaveCriticalSection 함수 호출로 끝 지점 지정
DeleteCriticalSection 함수 호출로 리소스 반환
인터락 함수 기반의 동기화 (유저 모드 동기화)
내부적으로 한순간에 하나의 쓰레드에 의해서만 실행되도록 동기화 되어있는 인터락 함수를 사용하는 것도 방법이다.
아래 함수의 경우 int 값을 넣었을때 1의 값이 증가, 감소 되는 인터락 함수이다.
MSDN 에서 상황에 맞는 인터락 함수를 찾아 사용하는 것도 임계영역 문제점을 해결할 수 있는 방법 중 하나이다.
LONG InterlockedIncrement(
LONG volatile* Addend //값을 증가시킬 32bit 변수
);
LONG InterlockedDecrement(
LONG volatile* Addend ////값을 감소시킬 32bit 변수
);
4. 커널 모드의 동기화
뮤텍스 기반의 동기화 (커널 모드 동기화)
뮤텍스 기반 동기화는 커널 모드를 사용하고 뮤텍스는 커널 오브젝트 이기때문에
핸들을 반환하고 보안 속성(상속 등)을 지정할 수 있다.
7장에서 커널오브젝트는 Signaled 상태와 Non-Signaled 상태를 가진다고 설명한 바 있다.
프로세스의 경우 Signaled 상태에서 Non-Signaled 상태가 되지 않지만
뮤텍스 커널 오브젝트는 누군가 접근 가능 할때 Signaled, 이미 접근 중이면 Non-Signaled 상태가 된다.
6장에서 소개드렸던 WaitForSingleObject 함수를 사용해서 커널 오브젝트의 상태를 알수 있다.
WaitForSingleObject 함수는 인자로 전달된 커널 오브젝트가 Signaled 상태일 경우 Non-Signaled 로 만든다.
그렇기 때문에 진행중인 쓰레드가 ReleaseMutex 를 호출하기 전까지는 다른 쓰레드가 접근 할 수 없다.
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTE lpMutexAttribute, //보안속성 설정
BOOL bInitialOwner, //이 함수를 호출하는 쓰레드부터 호출 할건지
LPCTSTR lpName //이름을 전달하면 이름있는 뮤텍스 없으면 이름없는 뮤텍스
);
BOOL ReleaseMutex(
HANDLE hMutex //반환될 뮤테스의 핸들
);
//============================================= 아래는 진행 순서
CreateMutex 함수 호출로 뮤텍스 핸들 얻어옴
WaitForSingleObject 함수 호출로 시작 지점 지정
//임계 영역//
ReleaseMutex 함수 호출로 끝 지점 지정
CloseHandle 함수 호출로 리소스 반환
세마포어 기반의 동기화 (커널 모드 동기화)
뮤텍스는 세마포어의 일종이다.
뮤텍스와 설명드릴 세마포어의 차이점은 카운트라고 볼수 있다.
뮤텍스는 한번에 지정된 블록에 대해서 하나의 쓰레드만 접근이 가능하지만
세마포어 기반의 동기화는 접근 가능한 쓰레드의 수를 지정 할 수 있다.
접근 가능한 쓰레드의 수를 1 로 제한하면 뮤텍스 기반 동기화와 동일한 기능을 제공하게 된다.
세마포어는 lInitialCount 에 의해 초기 카운트가 결정된다.
0 일경우 Non-Signaled 상태 1 이상일 경우 Signaled 상태를 지니며
WaitForSingleObject 함수가 호출 될때마다 카운터의 숫자가 1씩 줄어들게 된다.
ReleaseSemaphore 함수를 통해 카운터를 올려 쓰레드의 수를 제한 할 수 있다.
HANDLE CreateSemaphore(
LPSECURITY_ATTRIBUTE lpMutexAttribute, //보안속성 설정
LONG lInitialCount, //접근 가능한 쓰레드의 수
LONG lMaximumCount, //세마포어가 가질 수 있는 최대값
LPCTSTR lpName //이름을 전달하면 이름있는 세마포어 없으면 이름없는 세마포어
);
BOOL ReleaseSemaphore(
HANDLE hSemaphore, //반환하는 세마포어 핸들
LONG lReleaseCount, //세마포어 카운트 증가값 (보통 1)
LPLONG lpPreviousCount //변경되기 전 세마포어 카운트 값
);
//============================================= 아래는 진행 순서
CreateSemaphore 함수 호출로 세마포어 핸들 얻어옴
WaitForSingleObject 함수 호출로 시작 지점 지정
//임계 영역//
ReleaseSemaphore 함수 호출로 끝 지점 지정
CloseHandle 함수 호출로 리소스 반환
이름있는 뮤텍스 기반의 프로세스 동기화 (커널 모드 동기화)
위 4가지 동기화 방법들은 같은 프로세스 내 쓰레드간 동기화방법이었다.
지금 소개 시켜드릴 내용은 프로세스가 다른 쓰레드간 동기화 방법이다.
뮤텍스는 커널 오브젝트이기 때문에 A 프로세스에서도 B 프로세스에서도 접근이 가능하다.
다만 뮤텍스를 생성한 프로세스만 뮤택스 커널 오브젝트의 핸들을 알고 있다는 것인데
A 와 B 관계가 없을때(부모 자식) 핸들을 넘겨줄 방법이 없기에 이름을 붙여주기로 한것이다.
아래 함수는 생성되어 있는 뮤텍스 커널 오브젝트의 핸들을 이름으로 찾아 반환하는 함수이다.
HANDLE OpenMutex(
DWORD dwDesiredAccess, //접근 권한 지정
BOOL bInheritHandle, //핸들 상속 여부
LPCTSTR lpName //얻고자 하는 핸들 정보의 커널 오브젝트 이흠
);
알고 넘어가야할 것
1. 유저모드 동기화와 커널 모드 동기화의 차이점과 장단점
2. 임계영역 의미
3. 뮤텍스와 세마포어의 차이점과 유사점
'윤성우 저자'님의 '뇌를 자극하는 윈도우즈 시스템 프로그래밍' 책을 보고 정리한 내용입니다.
'IT > 윈도우 시스템 프로그래밍' 카테고리의 다른 글
(윈도우 시스템) 16. 컴퓨터 구조 네번째 (0) | 2021.08.20 |
---|---|
(윈도우 시스템) 14. 쓰레드 동기화 기법 2 (실행순서의 동기화) (0) | 2021.08.18 |
(윈도우 시스템) 12. 쓰레드의 생성과 소멸 (0) | 2021.08.13 |
(윈도우 시스템) 11. 쓰레드의 이해 (0) | 2021.08.11 |
(윈도우 시스템) 10. 컴퓨터 구조 세번째 (0) | 2021.08.09 |