728x90

쓰레드의 성격과 특성

- 쓰레드는 힙, 데이터, 코드 영역을 공유함

    -> 전역변수를 쓰레드가 접근할 수 있음

#include <stdio.h>
#include <Windows.h>
#include <tchar.h>

static int total = 0;

DWORD WINAPI ThreadProc(LPVOID lpParam)
{
	DWORD* nptr = (DWORD*)lpParam;

	DWORD num1 = *nptr;
	DWORD num2 = *(nptr + 1);

	for (DWORD i = num1; i <= num2; i++)
	{
		total += i;
	}

	return 0;
}

int _tmain(int argc, TCHAR* argv[])
{
	DWORD	dwThreadId[3];
	HANDLE	hThread[3];

	DWORD param[] = { 1,3,4,7,8,10 };

	DWORD result = 0;
	hThread[0] = CreateThread(
		NULL,
		0,							// 스택의 크기 1MB로 설정
		ThreadProc,					// 쓰레드로 사용할 함수
		(LPVOID)(&param[0]),		// 쓰레드 함수의 전달 인자
		0,
		&dwThreadId[0]	// 쓰레드 ID 반환
	);
	hThread[1] = CreateThread(
		NULL,
		0,							// 스택의 크기 1MB로 설정
		ThreadProc,					// 쓰레드로 사용할 함수
		(LPVOID)(&param[2]),		// 쓰레드 함수의 전달 인자
		0,
		&dwThreadId[1]	// 쓰레드 ID 반환
	);
	hThread[2] = CreateThread(
		NULL,
		0,							// 스택의 크기 1MB로 설정
		ThreadProc,					// 쓰레드로 사용할 함수
		(LPVOID)(&param[4]),		// 쓰레드 함수의 전달 인자
		0,
		&dwThreadId[2]	// 쓰레드 ID 반환
	);

	if (hThread[0] == NULL || hThread[1] == NULL || hThread[2] == NULL)
	{
		_tprintf(_T("Thread create error\n"));
		return -1;
	} // 쓰레드를 생성하지 못하면 NULL이 반환

	WaitForMultipleObjects(3, hThread, TRUE, INFINITE);	// 쓰레드가 종료될 때까지 대기

	GetExitCodeThread(hThread[0], &result);
	total += result;
	GetExitCodeThread(hThread[1], &result);
	total += result;
	GetExitCodeThread(hThread[2], &result);
	total += result;

	_tprintf(_T("total (1~10) : %d\n"), total);

	CloseHandle(hThread[0]);
	CloseHandle(hThread[1]);
	CloseHandle(hThread[2]);

	return 0;
}

- 동시접근의 문제점

    -> 둘 이상의 쓰레드가 하나의 전역 변수에 접근을 하게 되면 문제가 일어날 수 있음

    -> 쓰레드 A가 연산을 하고 있는데 연산 값을 레지스터에 저장하고 다시 전역 변수에 반환해주기 전에 쓰레드 B가 running이 되어 컨텍스트 스위칭이 일어나는 경우 레지스터 정보를 잠시 메모리에 임시 저장 후 레지스터를 비워줌

    -> 쓰레드 B가 연산 후 전역 변수에 저장 후 쓰레드 A가 다시 running이 되면 임시 저장한 데이터를 레지스터로 다시 가져온 다음 전역 변수에 데이터를 저장함

    -> 이러한 문제를 방지하기 위해서는 쓰레드가 작업하는 동안에는 같은 메모리 영역을 접근하면 안됨

 

- 프로세스로부터 쓰레드 분리

    -> 쓰레드는 생성부터 UC가 2

    -> 쓰레드 종료시 -1이 되고 closeHandle() 호출 시 -1이 되어 0이 됨

    -> 쓰레드를 생성과 동시에 closeHandle()을 해주게 되면 쓰레드 종료시 UC가 0이 되게 됨 : 쓰레드 분리

        * 이럴 경우 쓰레드를 생성한 프로세스에서 쓰레드의 종료 코드를 얻을 수 없음

 

ANSI 표준 C라이브러리와 쓰레드

- ANSI 표준 C라이브러리는 쓰레드 기반에 안정적이지 않음

    -> 동시접근 문제

- CreateThread -> _beginthreadex

    -> _beginthreadex는 내부적으로 createThread 함수를 호출해주고 쓰레드별로 별도의 메모리 공간을 할당

- ExitThread -> _endthreadex

    -> _endthreadex는 할당한 메모리 공간을 해제함

 

728x90

+ Recent posts