코드 참조
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;


}
Posted by 카켈
코드 주소
http://kin.naver.com/db/detail.php?d1id=1&dir_id=10104&eid=9kk6jmd+YayvujZz7fRRjP8F0n0+o/Yc&qb=vrK3ubXl

코드 받기



수행 화면
사용자 삽입 이미지

코드 설명

병렬로 스레드를 수행할때 지연을 줬을때와 안 주었을때 그리고 함수로 순차 수행했을때 차이를 보여주는 예제 입니다.

코드 내용
/*
	저작권 표기
	네이버 지식인 : C 쓰레드 예제에서 에러가 납니다... 고수님들 도와주세요~~ 
	http://kin.naver.com/db/detail.php?d1id=1&dir_id=10104&eid=0bUQ1CpEfllQ+RSELTqBVtOEPnrGHJN/&qb=vrK3ubXl
	http://cakel.tistory.com

	교육용을 목적으로 자유롭게 배포 할수 있습니다.

	thread_dsp.cpp : 극한의 상황을 줘서 지연을 주었을때,
	안주었을 때의 스레드 처리 순서와 함수로 줬을때 처리 순서를 나타내는 프로그램입니다.
        WIN32 의 함수를 사용했습니다.


*/

#include <process.h>
#include <stdio.h>
#include <windows.h>
#include <conio.h>

void dsp1(void *param)
{	// 100 ms 를 단위로 한줄을 출력을 하는 함수 입니다.
	int i = 0;
	for (i=0; i<10; i++)
	{
		printf("[1]%d\n",i);
		Sleep(100);
	}

	printf("dsp1 수행 완료\n");

}

void dsp2(void *param)
{	// 100 ms 를 단위로 한줄을 출력을 하는 함수 입니다.
	int i = 0;
	for (i = 0; i< 10; i++)
	{
		printf("[2]%d\n", i);
		Sleep(100);
	}

	printf("dsp2 수행 완료\n");

}

void dsp3(void *param)
{	// delay 없이 한줄을 바로 출력하는 함수입니다.
	int i = 0;
	for (i=0; i<10; i++)
	{
		printf("[3]%d\n",i);
	}

	printf("dsp3 수행 완료\n");

}

void dsp4(void *param)
{	// delay 없이 한줄을 바로 출력하는 함수입니다.
	int i = 0;
	for (i = 0; i< 10; i++)
	{
		printf("[4]%d\n", i);
		}

	printf("dsp4 수행 완료\n");

}

int main()
{
	// 스레드의 주소를 담는 핸들을 선언합니다.
	HANDLE th1, th2;
	
	// Race condition(경쟁조건) 에서 수행합니다.
	printf("Sleep(100)을 쓰고 스레드 1, 2를 실행 합니다.\n");
	th1 = (HANDLE)_beginthread(dsp1, 0, NULL);
	th2 = (HANDLE)_beginthread(dsp2, 0, NULL);

	// 스레드 완료를 위해 무한으로 기다립니다.
	WaitForSingleObject(th1, INFINITE);
	WaitForSingleObject(th2, INFINITE);

	printf("아무키를 치면 다시 딜레이 없이 바로 스레드 3, 4를 실행합니다.\n");
	
	_getch();	// 아무키를 입력받습니다.

	// 원래는 1번과 2번 스레드가 동시에 일어나므로 느린 PC 에서는 같이 출력될수 있습니다.
	
	// 다시 스레드를 구동합니다.
	th1 = (HANDLE)_beginthread(dsp3, 0, NULL);
	th2 = (HANDLE)_beginthread(dsp4, 0, NULL);

	// 스레드 완료를 위해 무한으로 기다립니다.
	WaitForSingleObject(th1, INFINITE);
	WaitForSingleObject(th2, INFINITE);

	printf("아무키를 치면 하나의 Sleep(100)을 쓴 함수 1, 2(프로시져)로 수행합니다.\n");

	_getch();	// 아무키를 입력받습니다.

	// 단일 함수로써 dsp1(), dsp2() 함수로 호출합니다.
	// NULL 과 0 은 같은 역할을 합니다.
	dsp1(NULL);
	dsp2(0);

	printf("수행완료 프로그램 끝\n");

	return 0;

}
Posted by 카켈
코드 출처
http://www.warpspeed.com.au/cgi-bin/inf2html.cmd?..\html\book\Toolkt40\XPG4REF.INF+101
바로 받기




코드 개요
스레드를 강제 종료하는 내용과 스레드 수행 대기를 담았습니다.

실행 화면
사용자 삽입 이미지

코드 설명
/*
	스레드 프로그래밍 연습 - 2 : 스레드 강제 종료
	thread_end.cpp

	저작권
	http://www.warpspeed.com.au/cgi-bin/inf2html.cmd?..\html\book\Toolkt40\XPG4REF.INF+101 - 출처
	http:/cakel.tistory.com - 번역/수정
	교육용을 목적으로 자유롭게 배포가 가능합니다.

	스레드를 생성한 후 강제 종료하는 방법의 예를 기술한 문서입니다.

*/

#include <stdio.h>
#include <process.h>
#include <windows.h>

/*

+	_endthread() - 최근에 수행을 시작한 스레드가 강제종료 됩니다.
	_beginthread() 와 같이 씁니다. (WIN32용)
	 closethread() 와는 다른 방식으로 생성 되므로 closethread()
	 함수는 createthread() 와 맞춰 쓰시면 됩니다. (MFC용)
	 용도에 따라 다른 쓰레드 함수를 쓰시기 바랍니다.

*/

void hello(void *arg)
{
	int i = 0;
	while (i++ < 5)
	{
		printf("안녕하세요!\n");
		
	}
	_endthread();		// 여기 까지 실행하고 종료 됩니다.
	puts("hello 스레드가 여길 실행하지 못하고 종료 합니다."); 
	return;

}

void nice(void *arg)
{
	int i = 0;
	while (i++ < 5)
	{
		printf("반갑습니다!\n");

	}
	// 스레드가 명시된 곳 까지 수행할수 있습니다.
	puts("nice 스레드가 여기까지 수행하고 종료 합니다.");

	return;
}

int main(void)
{
	// 스레드의 수행 주소를 담은 핸들
	HANDLE thread_1, thread_2;

	// 스레드 활성화(Activation)
	thread_1 = (HANDLE) _beginthread(hello, 0, NULL);
	thread_2 = (HANDLE) _beginthread(nice, 0, NULL);

	// 메인 스레드인 main() 함수가 먼저 return 0 로 도달하면
	
	/* WaitForSingleObject(스레드 주소, 시간)
	 스레드가 다 실행 못하고 끝이 나므로 WaitForSingleObject
	 함수를 써서 해당 스레드가 끝날때 까지 기다려 줍니다.
	 시간이 INFINITE 는 예약어로써 무한대로 기다려준다는 뜻입니다.
	
	*/
	
	
	/* _beginthread 가 long 형으로 수행주소를 리턴 하지만
		WaitForSingleObject 에서 받는 스레드 주소는 void* 로 받기
		때문에 void* 형인 HANDLE 로 스레드 주소를 저장합니다.
		long* 주소를 void* 으로 형 변환합니다.
		void 포인터(void* ) 는 범용으로 주소를 형변환 하면 자유자재로
		받을수 있습니다. 대신 내 보낼때 특정 형식에 맞춰서 보내지 않으면
		얘기치 못한 오류가 생길수 있습니다. */

	WaitForSingleObject(thread_1, INFINITE);
	WaitForSingleObject(thread_2, INFINITE);

	printf("생성된 스레드가 종료 되었습니다.\n");

	return 0;

}
Posted by 카켈
코드 참조
http://keegan.tistory.com/144

코드 받기


실행 화면
사용자 삽입 이미지

컴파일시 주의
프로젝트 설정(Alt + F7)에서 코드 생성 항목에서 Use run time libary 에 Debug Multithreaded 로 맞춰 주시면 됩니다.

사용자 삽입 이미지



코드 설명
/*
	- 스레드 프로그래밍 연습 - 1 : 스레드 생성
	
	- 저작권 알림
	http://keegan.tistory.com/144 - 원본
	http://cakel.tistory.com - 수정
        교육용을 목적으로 자유롭게 쓰실수 있습니다.

	- 코드 : thread.cpp
        스레드 구현하여 각각 다른 글자들을 출력하는 내용입니다. 
	WIN32 C++ 용입니다.


*/

// #include <헤더>	      // 필요한 함수
#include <windows.h>		// Sleep()
#include <stdio.h>		// printf(), fprintf()
#include <process.h>		// _beginthread();
#include <conio.h>		// _getch()

// 전역 변수
int repeatA;
int repeatB;

void PrintA(void *pData);	// 첫번째 스레드
void PrintB(void *pData);	// 두번째 스레드

int main()
{
	int ch;

	// fprintf()
	// 입출력 스트림으로 해당 내용을 출력합니다.
	// stdout 이 화면이므로, printf 함수와 크게 다르지 않게 작동합니다.
	fprintf(stdout,"a, b 를 입력하면 출력하지 않습니다. 다른키를 누르면 종료합니다.\n");
	fprintf(stdout,"시작!\n");
	
	// _beginthread(함수명, 스택크기, 단일인수)
	// 스택크기는 0으로 하면 운영체제에서 알아서 넣어 줍니다.
	// 보통 void* 으로 세번째 인수를 쓰는데, 복잡하게 쓸수도 있습니다.
	
	// 스레드는 변수를 공유하면서도 프로세스내에서 병렬적으로 같이 실행할수 있는
	// 부프로그램입니다.
	_beginthread(PrintA, 0, NULL);
	_beginthread(PrintB, 0, NULL);

	repeatA = 1;
	repeatB = 1;

	while(1)
	{		
		// 키보드 입력을 받는 메인 스레드에서 Ctrl + C 눌르거나
		// 다른키를 눌러서 return 으로 버리면 이미 생성된 스레드도 동반 종료 합니다.

		// _getch() : getchar() 함수와 달리 엔터를 치지 않아도
		// 한번의 키보드 입력으로 들어온 값을 바로 버퍼에 들어가서
		// 실행이 완료되는 함수 입니다. conio.h 헤더를 이용합니다.


		ch = _getch();
		if (ch == 'a')
			repeatA = 0;

		else if(ch == 'b')
			repeatB = 0;

		else
			break;


	}

	return 1;

}

void PrintA(void* pData)
{
	while(repeatA)
	{printf(" a ");
	Sleep(1000);}
	return;

}

void PrintB(void *pData)
{
	while(repeatB)
	{printf(" b ");
	Sleep(1000);}
	return;

}
Posted by 카켈


Teach yourself Visual C++ in 21days 의 18일차 코드입니다.
제목은 한 번에 여러 작업을 한다 - 다중작업 입니다.

  슬슬 하란데로 하다간 지칠 코드 입니다. static 으로 선언될 부분을 잘 기억 하시고 맴버 변수일때는 클래스의 바깥에서 한번더 정의를 시켜 줘야지 링크 오류가 생기지 않습니다. 책에서는 언급이 없어서 어쳐구니 없는 unresolved symbol error 가 2번이나 발생했습니다.

간단하지만 생각해서 치기까지 상당히 고민 했습니다. 18일차입니다. 이제 3일 남았네요. 이번 코드는 생각보다 효율은 그렇게 좋지 않은거 같습니다. 역시 어렵군요.

MFC 아이콘이 좋아 보여서 가져 왔는데, 색깔이 영 지저분 하네요.
Posted by 카켈
이전페이지 1 다음페이지