예를 들어 8개의 스레드가 돌고 있는데 모두 같은 리소스를 사용한다고 가정 하면 이 스레드들은 레이싱 컨디션에 들어간다.
이 때, 크리티컬 섹션/뮤텍스를 사용하면 7개를 스탑시키고 한개를 리소스에 접근시켜야 함
그러나 세마포어는 2개이상의 스레드를 접근시키고 나머지는 대기할 수 있도록 하는 것이 가능하다.
따라서 크리티컬 섹션/뮤텍스는 두 개의 스레드를 교차 실행 시켜야 할 때.
1. 프로젝트 생성, 단일문서기반, (서비스팩이 설치되어 있다면 오피스 2003)
2. stdafx.cpp
CString g_arString[10];
CSemaphore g_SP(3,3);
stdafx.h에 <afxmt.h>인클루드
extern CString g_arString[10];
extern CSemaphore g_SP;
3. Semaphore.h파일의 CwinApp클래스에 CEvent 객체 추가
class CSemaphoreApp : public CWinApp
{
public:
CSemaphoreApp();
CEvent m_ExitEvent; // 종료이벤트
객체 초기화-> 생성자를 부른다.어플리케이션 클래스의 생성자 함수 안에서 초기화
CSemaphoreApp::CSemaphoreApp()
:m_ExitEvent(FALSE, TRUE)
{
// TODO: 여기에 생성 코드를 추가합니다.
// InitInstance에 모든 중요한 초기화 작업을 배치합니다.
}
4. SemaphoreApp에 ExitInstance() 함수 재정의
int CSemaphoreApp::ExitInstance()
{
m_ExitEvent.SetEvent();
::Sleep(1000);
return CWinApp::ExitInstance();
}
5. 특정 클래스 안에 멤버함수로 스레드 만들기(지난번에 한것은 전역함수로 스레드를 만듬)
SemaphoreApp클래스 속성에서 함수 추가
반환 형식: UINT
매개 변수 형식: LPVOID
함수 이름: threadSemaphore
액세스: public
매개 변수 이름: pParam 추가
static(정적함수) 생성
주석: App 클래스에 멤버로서 포함되어진 스레드
-> 실제 함수 추가시에 직접 코드를 작성하는 것이 더 편할 수 있다.
하지만 마법사를 이용할경우 헤더파일에 선언부를 자동으로 함께 만들어준다는 장점이 있다.
UINT CSemaphoreApp::ThreadSemaphore(LPVOID pParam)
{
CString strTmp = _T("");
int nIndex = (int)(pParam);
g_arString[nIndex] = _T("");
while(::WaitForSingleObject(theApp.m_ExitEvent, 10) == WAIT_TIMEOUT)
{
g_arString[nIndex].Format(TEXT("%d Thread is waiting!!"), nIndex);
g_SP.Lock();
g_arString[nIndex].Format(TEXT("##%d Thread is running!!"), nIndex);
::Sleep(100);
g_SP.Unlock();
}
return 0;
}
6. Semaphore.cpp에
for(int i=0; i<10; ++i)
{
AfxBeginThread(CSemaphoreApp::ThreadSemaphore, (LPVOID)i);
}
7. 화면에 뭔가 보여주기 위한 작업
뷰클래스에 WM_Create메시지 추가, 여기에 타이머 설정
int CSemaphoreView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
SetTimer(100, 1000, NULL);
// TODO: 여기에 특수화된 작성 코드를 추가합니다.
return 0;
}
뷰클래스에 WM_Timer메시지 추가
void CSemaphoreView::OnTimer(UINT_PTR nIDEvent)
{
CClientDC dc(this);
dc.FillSolidRect(0, 0, 300, 300, RGB(255, 255, 255));
for (int i=0;i<10;i++)
{
if(g_arString[i].GetAt(0) == '#')
dc.SetTextColor(RGB(192, 0, 0));
else
dc.SetTextColor(RGB(192, 192, 192));
dc.TextOut(30, 20 * i + 10, g_arString[i]);
}
CView::OnTimer(nIDEvent);
}
OS가(커널) 스레드를 대기시키고 다른 스레드를 실행하는 기준?
UINT CSemaphoreApp::ThreadSemaphore(LPVOID pParam)
{
CString strTmp = _T("");
int nIndex = (int)(pParam);
g_arString[nIndex] = _T("");
while(::WaitForSingleObject(theApp.m_ExitEvent, 10) == WAIT_TIMEOUT)
{
g_arString[nIndex].Format(TEXT("%d Thread is waiting!!"), nIndex);
g_SP.Lock();
g_arString[nIndex].Format(TEXT("##%d Thread is running!!"), nIndex);
::Sleep(100);
g_SP.Unlock();
}
return 0;
}
--> 여기서 while문의 이해가 중요
/*다음의 의미를 구별*/
이벤트: 키보드/마우스의 움직임과 같은 행위 그 자체. 행위를 나타내는 일종의 신호(데이터)
메시지:
이벤트 처리기:
메시지 처리기(메시지 처리 함수): 이벤트의 신호에 대응해서 큐에 들어온 메시지를 처리하는 함수
<크리티컬섹션/뮤텍스/세마포어>
스레드를 멈추는것이 목적이 아님.
실행되고 있는 스레드끼리 부딪히는것을 막음.
'PROGRAMMING > MFC(C++)' 카테고리의 다른 글
[0422수업] 중복실행 방지 (0) | 2011.04.22 |
---|---|
[0421수업] 소프트웨어 업데이트 (0) | 2011.04.21 |
[0418수업] ThreadCrash(Critical Section, 뮤텍스) (0) | 2011.04.18 |
[본문스크랩] |소켓 프로그래밍| 멀티 스레드(스레드 동기화) ③ (0) | 2011.04.15 |
[0415수업] UIThread(Suspend Thread, Resume Thread) (0) | 2011.04.15 |