학교/컴퓨터통신
스레드 프로그래밍 연습 - 4 : mutex
카켈
2007. 5. 2. 19:08
코드 참조
http://tong.nate.com/haru3173/24195740
http://blog.naver.com/gamed21/70015497269
코드 받기
수행 화면
코드 설명
세개의 스레드가 mutex 로 공유된 변수를 접근하는 내용입니다. 장점과 문제점을 동시에 가지고 있는 코드입니다.
코드 내용
http://tong.nate.com/haru3173/24195740
http://blog.naver.com/gamed21/70015497269
코드 받기
수행 화면
세개의 스레드가 mutex 로 공유된 변수를 접근하는 내용입니다. 장점과 문제점을 동시에 가지고 있는 코드입니다.
코드 내용
/* 스레드 프로그래밍 연습 - 4 : mutex mutex_ex.cpp 저작권 http://cakel.tistory.com 참조 코드 http://tong.nate.com/haru3173/24195740 http://blog.naver.com/gamed21/70015497269 교육용을 목적으로 자유롭게 사용하실수 있습니다. WIN32 로 만들어진 간단한 mutex 가 사용된 스레드 프로그램입니다. 1번 스레드는 10을 더하는 내용을 2번 스레드는 5를 빼는 내용을 3번 스레드는 지정된 검사값을 탐지하는 내용을 갖고 있습니다. mutex 의 성질을 십분 활용했습니다. 문제점도 가지고 있습니다. */ #include <stdio.h> // printf() #include <windows.h> // Sleep(), HANDLE, CloseHandle(), WaitForSingleObject(), ReleaseHandle() #include <process.h> // _beginthread() // Mutex 용 handle 은 전 스레드에서 쓰기 때문에 중복 선언 하는 거 보다 전역을 빼어 // 썼습니다. 스레드 내에서 쓰셔도 무방합니다. 단 CreateMutex() 함수 수행은 // main 내에서 해야지 디버그하기 용이 합니다. HANDLE hMutex = 0; // 이번에 공유할 변수 int nShare = 0; // 스레드 후보 함수들의 prototype (선선언 하여 이후에 참조해도 문법상 문제가 없게 합니다. // 문법상 문제가 없더라도 정의를 하지 않는다면 Link 오류가 생깁니다. void tPlus(void*); // 덧셈 void tMinus(void*); // 뺄셈 void tDetect(void*); // 감지용 int main() { HANDLE hTh1, hTh2, hTh3; hMutex = CreateMutex(NULL, FALSE, NULL); // 생성된 mutex 가 유효한지 확인합니다. if(hMutex == NULL) { printf("뮤택스 생성 실패 했습니다.\n"); return 1; } // 변화 시킬 값입니다. // int nPlus = 10; // tPlus 수행시 증가될 값 int nMinus = 5; // nMinus 수행시 감소될 값 int nDetect = 30; // 30을 감지 합니다. // 단계를 밟을 값입니다. int i = 0; while(i < 10) // 예상은 총 10회 (0 ~ 9) { // 스레드를 받아 유효한지 확인도 하고 종료를 기다리게 만들 핸들을 선언합니다. hTh1 = (HANDLE) _beginthread(tPlus,0,(void*)&nPlus); hTh2 = (HANDLE) _beginthread(tMinus,0,(void*)&nMinus); hTh3 = (HANDLE) _beginthread(tDetect,0,(void*)&nDetect); // 유효성 검토 if (hTh1 == 0 || hTh2 == 0 || hTh3 == 0) // 하나라도 불량이면 나가 떨어집니다. { printf("스레드 생성 오류 입니다.\n"); return 1; } // hTh3 만 막아 줘야지 만약 그렇지 않고 계산 중의 수를 변화 탐지 할수가 없을수 있습니다. // hTh3 가 수행되기 전에 먼저 hTh1 과 hTh2 가 먼저 계산이 될수 있기 때문입니다. // WaitForSingleObject(hTh1, INFINITE); // WaitForSingleObject(hTh2, INFINITE); WaitForSingleObject(hTh3, INFINITE); i++; // 스레드의 수행이 끝나면 한단계를 증가 합니다. } // 마지막으로 열어둔 핸들을 닫습니다. CloseHandle(hTh1); CloseHandle(hTh2); CloseHandle(hTh3); CloseHandle(hMutex); return 0; } void tPlus(void *pData) { // void 포인터로 받으면 받을 값을 미리 알아 둬야 할 불편함이 있습니다. // 형변환을 해야 하니깐요. // Mutex 핸들을 활성화 하여 전역 변수를 단일 스레드만 접근할수 있게 합니다. // WAIT_FAILED 는 WaitForSingleObject() 함수 수행 결과가 실패 했으면 스레드가 정상 // 수행 되지 않기 때문에 안전 장치로 추가했습니다. if(WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED) { printf("스레드 Wait 오류\n 스레드 종료\n"); return; } // Dereference 값 참조 (void* -> int*) int 형 주소로 void 형 주소를 강제 // 변환한후 값을 가져 오는 방식입니다. 바로 void* 를 값 참조 할수 없습니다. nShare += *(int*)pData; printf("스레드 1 : Plus 계산후 nShare, : %d\n", nShare); // Sleep() 을 ReleaseMutex 밖에서 하니깐 문제가 발생했습니다. // hMutex 를 전역위치에서 CreateMutex() 쓰니깐 Sleep() 에서 문제가 발생했습니다. // 작동을 하지 않았습니다. Sleep(1000); // Mutex 를 풀어서 전역 변수의 독점을 해제 합니다. ReleaseMutex(hMutex); } void tMinus(void *pData) { // tPlus 함수와 크게 다르지 않습니다. if(WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED) { printf("스레드 Wait 오류\n 스레드 종료\n"); return; } nShare -= *(int*)pData; printf("스레드 2 : Minus 계산후 nShare : %d\n", nShare); // Mutex 를 풀어서 전역 변수의 독점을 해제 합니다. Sleep(200); ReleaseMutex(hMutex); } void tDetect(void *nDetect) { // tDetect 비교 if(WaitForSingleObject(hMutex, INFINITE) == WAIT_FAILED) { printf("스레드 Wait 오류\n 스레드 종료\n"); return; } printf("스레드 3 : 검사 - %d == %d\n", *(int*)nDetect, nShare); if (nShare == *(int*)nDetect) { // Mutex 의 한계로 덧셈 뺄샘 한 결과가 저장된 nShare 값을 탐지하므로 값이 실시간으로 잡지 못합니다. printf("%d 이 검사값과 일치\n", *(int*)nDetect); } // Mutex 를 풀어서 전역 변수의 독점을 해제 합니다. ReleaseMutex(hMutex); return; }