스레드
스레드는 레지스터, PC, 스택으로 구성되는 CPU 이용의 기본 단위이다.
다중 스레드 장점
1. 응답성
: 사용자 인터페이스를 설계하는데 있어서 유용하다. 예를 들어, 대화형 응용을 다중 스레드화함으로서 사용자의 긴 응답 요청을 기다릴 수 있다. 만약, 사용자가 연산이 오래 걸리는 요청을 할 떄, 단일 스레드와 비교하여 멀티 스레드는 비동기적 스레드에 의하여 사용자에게 여러 작업이 가능하게 한다.
2. 자원 공유
: 프로세스는 공유 메모리와 메시지 전달 기법을 통해 자원을 공유할 수 있다. 스레드는 본인이 속한 스레드의 자원들과 메모리를 공유한다. 이는 같은 메모리 주소 공간 내에 여러 개의 다른 작업을 하는 스레드를 가질 수 있다.
3. 경제성
: 스레드 생성이 프로세스 생성에 비하여 상대적으로 메모리와 자원 할당의 비용이 적게 든다.
4. 규모 적응성
: 다중 처리기 구조에서 각각의 스레드가 다른 처리기에서 병렬로 수행될 수 있다.
다중 코어 프로그래밍 병렬 실행의 유형
데이터 병렬 실행과 태스크 병렬 실행의 두 가지 유형이 존재한다.
데이터 병렬 실행은 동일한 데이터의 부분집합을 다수의 코어에 동일한 연산을 하는데 초점을 둔다.
태스크 병렬 실행의 초점은 데이터가 아닌 다수의 코어에 분배에 있다. 기본적인 데이터 병렬 처리에는 여러 코어에 데이터를 분배하는 것이 포함된다.
다중 스레드 모델
1. 다대일 모델
다대일 모델은 여러 사용자의 스레드를 하나의 커널 스레드로 사상한다. 스레드 관리는 사용자 공간의 스레드 라이브러리에 의해 행해진다. 하지만, 한 스레드가 봉쇄되어졌을 경우에는 전체 프로세스가 봉쇄된다. 한번에, 하나의 스레드만이 접근할 수 있기 때문에, 다중 스레드가 다중 코어 시스템에서 병렬로 실행되어질 수 없다.
2. 다대다 모델
여러 개의 사용자 수준 스레드를 여러 커널 스레드로 멀티 플렉스한다. 커널 스레드의 수는 응용 프로그램이나 특정 기계에 따라 결정된다. 다대일 모델은 개발자가 원하는 만큼의 스레드 생성을 허용하지만, 커널은 한 번에 하나의 커널 스레드만 스케줄 할 수 있기 때문에 진정한 병렬 실행을 획득할 수 없다. 따라서 tow-level-model 이라고 부르며, 스레드가 봉쇄형 시스템 콜을 발생시켰을 때, 커널이 다른 스레드의 수행을 스케줄 할 수 있다.
대부분의 시스템에서 처리 코어 수가 증가함에 따라 커널 스레드 수를 제한하는 것의 중요성이 줄어들었다. 따라서 대부분의 운영체제는 일대일 모델을 사용한다.
3. 일대일 모델
일대일 모델은 각 사용자 스레드를 각각 하나의 커널 스레드로 사상한다. 이 모델은 하나의 스레드가 봉쇄 시스템 콜을 호출하더라도 다른 스레드가 실행할 수 있기 떄문에 병렬성을 제공한다.
스레드 라이브러리
현재 POSIX Pthreads, Windows 및 Java의 세 종류 라이브러리가 사용된다.
Pthreads
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *print_message_function( void *ptr );
main()
{
pthread_t thread1, thread2;
char *message1 = "Thread 1";
char *message2 = "Thread 2";
int iret1, iret2;
/* Create independent threads each of which will execute function */
iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);
/* Wait till threads are complete before main continues. Unless we */
/* wait we run the risk of executing an exit which will terminate */
/* the process and all threads before the threads have completed. */
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
printf("Thread 1 returns: %d\n",iret1);
printf("Thread 2 returns: %d\n",iret2);
exit(0);
}
void *print_message_function( void *ptr )
{
char *message;
message = (char *) ptr;
printf("%s \n", message);
}
자세한 내용은 아래를 참고하면 된다.
https://www.cs.cmu.edu/afs/cs/academic/class/15492-f07/www/pthreads.html
Windows Thread
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#define MAX_THREADS 3
#define BUF_SIZE 255
DWORD WINAPI MyThreadFunction( LPVOID lpParam );
void ErrorHandler(LPCTSTR lpszFunction);
// Sample custom data structure for threads to use.
// This is passed by void pointer so it can be any data type
// that can be passed using a single void pointer (LPVOID).
typedef struct MyData {
int val1;
int val2;
} MYDATA, *PMYDATA;
int _tmain()
{
PMYDATA pDataArray[MAX_THREADS];
DWORD dwThreadIdArray[MAX_THREADS];
HANDLE hThreadArray[MAX_THREADS];
// Create MAX_THREADS worker threads.
for( int i=0; i<MAX_THREADS; i++ )
{
// Allocate memory for thread data.
pDataArray[i] = (PMYDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(MYDATA));
if( pDataArray[i] == NULL )
{
// If the array allocation fails, the system is out of memory
// so there is no point in trying to print an error message.
// Just terminate execution.
ExitProcess(2);
}
// Generate unique data for each thread to work with.
pDataArray[i]->val1 = i;
pDataArray[i]->val2 = i+100;
// Create the thread to begin execution on its own.
hThreadArray[i] = CreateThread(
NULL, // default security attributes
0, // use default stack size
MyThreadFunction, // thread function name
pDataArray[i], // argument to thread function
0, // use default creation flags
&dwThreadIdArray[i]); // returns the thread identifier
// Check the return value for success.
// If CreateThread fails, terminate execution.
// This will automatically clean up threads and memory.
if (hThreadArray[i] == NULL)
{
ErrorHandler(TEXT("CreateThread"));
ExitProcess(3);
}
} // End of main thread creation loop.
// Wait until all threads have terminated.
WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);
// Close all thread handles and free memory allocations.
for(int i=0; i<MAX_THREADS; i++)
{
CloseHandle(hThreadArray[i]);
if(pDataArray[i] != NULL)
{
HeapFree(GetProcessHeap(), 0, pDataArray[i]);
pDataArray[i] = NULL; // Ensure address is not reused.
}
}
return 0;
}
DWORD WINAPI MyThreadFunction( LPVOID lpParam )
{
HANDLE hStdout;
PMYDATA pDataArray;
TCHAR msgBuf[BUF_SIZE];
size_t cchStringSize;
DWORD dwChars;
// Make sure there is a console to receive output results.
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if( hStdout == INVALID_HANDLE_VALUE )
return 1;
// Cast the parameter to the correct data type.
// The pointer is known to be valid because
// it was checked for NULL before the thread was created.
pDataArray = (PMYDATA)lpParam;
// Print the parameter values using thread-safe functions.
StringCchPrintf(msgBuf, BUF_SIZE, TEXT("Parameters = %d, %d\n"),
pDataArray->val1, pDataArray->val2);
StringCchLength(msgBuf, BUF_SIZE, &cchStringSize);
WriteConsole(hStdout, msgBuf, (DWORD)cchStringSize, &dwChars, NULL);
return 0;
}
void ErrorHandler(LPCTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code.
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
// Display the error message.
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK);
// Free error-handling buffer allocations.
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
'운영체제' 카테고리의 다른 글
프로세스 간 통신 (0) | 2024.12.11 |
---|---|
프로세스 동기화 문제 (0) | 2024.11.22 |
운영체제 구조 (0) | 2024.09.14 |