Chapter 05. Multithread
Understanding basic multithread concept Coding TCP server multithread Goal Understanding basic multithread concept Coding TCP server multithread Learning thread synchronization methods
Terms Process and thread (1/2) process thread primary thread one executing instance of a “program” It’s separate from other instances Contains code (text), data, stack, heap thread a light-weighted process primary thread Thread that is executed in main() or WinMain() context switch occurs when the kernel switches from executing one thread to executing another. The kernel saves the context of the currently running thread and resumes the context of the next thread that is scheduled to run.
Threads: Lightweight Processes execution Environment (resource) (a) Three processes each with one thread (b) One process with three threads
Context switching process Process and thread (2/2) Context switching process CPU ① ② thread① register thread②
thread creation and termination (1/6) Elements for thread creation Starting address of thread function Stack region for thread function execution
thread creation and termination (2/6) f() { ... } main() Execution stack of Primary thread Thread ① code Thread ② thread ①, ② address space of process Two functions Three threads
thread creation and termination (3/6) CreateThread() function Return thread handle after thread creation HANDLE CreateThread ( LPSECURITY_ATTRIBUTES lpThreadAttributes, // NULL SIZE_T dwStackSize, // 0 LPTHREAD_START_ROUTINE lpStartAddress, //thread function LPVOID lpParameter, // thread function argument DWORD dwCreationFlags, // 0 or CREATE_SUSPENDED LPDWORD lpThreadId // thread ID ) ; success: thread handle, fail: NULL
thread creation and termination (4/6) Thread function definition DWORD WINAPI ThreadProc (LPVOID lpParameter) { ... }
thread creation and termination (5/6) Ways to terminate thread ① when thread function finish ② call ExitThread() function in thread function ③ call TerminateThread() function ④ all threads are terminated when primay thread is terminated ExThread1.cpp
thread creation and termination (6/6) Thread termination functions void ExitThread ( DWORD dwExitCode // exit code ) ; BOOL TerminateThread ( HANDLE hThread, // thread handle to terminate DWORD dwExitCode // exit code ) ; success: some value except 0, fail: 0
thread handling – priority (1/5) Terms thread scheduling Scheduling CPU time to each thread priority class Process property, All threads in a process have same priority class priority level Thread property, A thread in a process may have different priority base priority Combination of priority class and priority level Used in thread scheduling
thread handling – priority (2/5) Priority class REALTIME_PRIORITY_CLASS HIGH_PRIORITY_CLASS ABOVE_NORMAL_PRIORITY_CLASS NORMAL_PRIORITY_CLASS BELOW_NORMAL_PRIORITY_CLASS IDLE_PRIORITY_CLASS
thread handling – priority (3/5) Priority level THREAD_PRIORITY_TIME_CRITICAL THREAD_PRIORITY_HIGHEST THREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_NORMAL THREAD_PRIORITY_BELOW_NORMAL THREAD_PRIORITY_LOWEST THREAD_PRIORITY_IDLE
thread handling – priority (4/5) Priority based thread scheduling ... scheduler CPU thread (low) priority (high) Three threads in turn
thread handling – priority (5/5) Priority level handling function ExThread2.cpp BOOL SetThreadPriority ( HANDLE hThread, // thread handle int nPriority // priority level value ) ; success: some value except 0, fail: 0 int GetThreadPriority ( HANDLE hThread // thread handle ) ; success: priority level value, fail: THREAD_PRIORITY_ERROR_RETURN
thread handling – waiting thread termination (1/4) WaitForSingleObject() function Waiting for the termination of single thread WaitForSingleObject() function example DWORD WaitForSingleObject ( HANDLE hHandle, DWORD dwMilliseconds ) ; success: WAIT_OBJECT_0 or WAIT_TIMEOUT, fail: WAIT_FAILED HANDLE hThread = CreateThread(...); WaitForSingleObject(hThread, INFINITE);
thread handling – waiting thread termination (2/4) WaitForMultipleObjects() function Waiting for the termination of two threads or more DWORD WaitForMultipleObjects ( DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds ) ; success: WAIT_OBJECT_0 ~ WAIT_OBJECT_0 + nCount-1 or WAIT_TIMEOUT, fail: WAIT_FAILED
thread handling – waiting thread termination (3/4) WaitForMultipleObjects() function example ① // waiting for the termination of all threads HANDLE hThread[2]; HANDLE hThread[0] = CreateThread(...); HANDLE hThread[1] = CreateThread(...); WaitForMultipleObjects(2, hThread, TRUE, INFINITE);
thread handling – waiting thread termination (4/4) WaitForMultipleObjects() function example ② // waiting for one thread termination of two threads HANDLE hThread[2]; HANDLE hThread[0] = CreateThread(...); HANDLE hThread[1] = CreateThread(...); DWORD retval = WaitForMultipleObjects(2, hThread, FALSE, INFINITE); switch(retval){ case WAIT_OBJECT_0: // hThread[0] termination break; case WAIT_OBJECT_0+1: // hThread[1] termination case WAIT_FAILED: // error }
thread handling – suspend and resume (1/2) Suspend function ① Resume function DWORD SuspendThread ( HANDLE hThread // thread handle ) ; success: num of suspend, fail: -1 DWORD ResumeThread ( HANDLE hThread // thread handle ) ; success: num of suspend, fail: -1
thread handling – suspend and resume (2/2) Sleep function ② Thread stop and wait for the defind time ExThread3.cpp void Sleep ( DWORD dwMilliseconds // millisecond(ms) ) ;
Multithread TCP Server (1/3) Basic structure DWORD WINAPI ProcessClient(LPVOID arg) { // socket transfer ③ SOCKET client_sock = (SOCKET)arg; // getting client information ④ addrlen = sizeof(clientaddr); getpeername(client_sock, (SOCKADDR *)&clientaddr, &addrlen); // data comm. with client ⑤ while(1){ ... } closesocket(client_sock); return 0;
Multithread TCP Server (2/3) Basic structure (cont’d) int main(int argc, char* argv[]) { ... while(1){ // accept client connection ① client_sock = accept(listen_sock, ...); // thread creation ② CreateThread(NULL, 0, ProcessClient, (LPVOID)client_sock, 0, &ThreadId); }
Multithread TCP Server (3/3) Getting socket-related address information TCPServer2.cpp int getpeername ( SOCKET s, struct sockaddr* name, int* namelen ) ; success: 0, fail: SOCKET_ERROR int getsockname ( SOCKET s, struct sockaddr* name, int* namelen ) ; success: 0, fail: SOCKET_ERROR
thread synchronization (1/4) Why does thread synchronization need? When two or more threads access the shared data in multithread environment thread 1 int money = 1000 ... ① read money into ECX ② ECX = ECX + 2000 ③ write ECX into money thread 2 ② ECX = ECX + 4000 Shard variable
thread synchronization (2/4) Various thread synchronization mechanism technique description critical section The critical section is a thread synchronization object (the critical section allows synchronization within the same process. ) mutex synchronization object used to synchronize the threads with more than one process. event Event is a thread synchronization object used to set the signaled or non-signaled state semaphore thread synchronization object that allows accessing the resource for a count between zero and maximum number of threads
critical section features Critical section allows accessing only one thread at a time features Thread synchronization within the process faster compared to other synchronization objects
Critical section example #include <windows.h> CRITICAL_SECTION cs; // ① // thread 1 DWORD WINAPI Thread1(LPVOID arg) { ... EnterCriticalSection(&cs); // ③ // access shared resource LeaveCriticalSection(&cs); // ④ }
Critical section example (cont’d) ExCriticalSection.cpp // thread 2 DWORD WINAPI Thread2(LPVOID arg) { ... EnterCriticalSection(&cs); // ③ // access shared resource LeaveCriticalSection(&cs); // ④ } int main() InitializeCriticalSection(&cs); // ② // thread creation and exit DeleteCriticalSection(&cs); // ⑤
Event synchronization example Event object (1/3) event object Used to notify a specific event to other thread Event synchronization example ① event object creation to non-signaled state ② a thread is working, remaining threads are waiting for event to be signaled state ③ when a thread finish the job, set the event to signal state ④ waiting threads are doing their jobs
Event object state setting Event types auto-reset event manual-reset event BOOL SetEvent (HANDLE hEvent) ; // non-signaled state signaled state BOOL ResetEvent (HANDLE hEvent) ; // signaled state non-signaled state
Event object creation ExEvent.cpp Event object (3/3) HANDLE CreateEvent ( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR lpName ) ; success: event handle, fail: NULL