Presentation is loading. Please wait.

Presentation is loading. Please wait.

Windows Thread Management

Similar presentations


Presentation on theme: "Windows Thread Management"— Presentation transcript:

1 Windows Thread Management

2 Objectives and Benefits
Describe Windows thread management Use threads in Windows applications Use threads with C library functions Build and execute threaded applications Describe the various Windows synchronization mechanisms Differentiate synchronization object features and how to select between them Use synchronization in Windows applications

3 Threads: Benefits and Risks
Simpler program models Faster code – in many cases Exploit multiple processors Exploit inherent application parallelism Reliable, understandable, maintainable code Risks Slower performance – in some cases Potential defects

4 Contents Process and Thread Overview Thread Management
Waiting for Thread Termination The C Library and Threads Demonstration: Building a Threaded Application Need for Synchronization Thread Synchronization Objects CRITICAL_SECTIONs (Deadlock Example) Mutexes for Mutual Exclusion Events Semaphores

5 1. Process and Thread Overview
Threads in a process share data and code Each thread has its own stack for function calls Calling thread can pass an argument to a thread at creation time This argument is on the stack Each thread can allocate its own Thread Local Storage (TLS) indices and set TLS values Threads are scheduled and run independently The executive schedules threads Threads run asynchronously Threads can be preempted Or restarted at any time

6 Processes and Threads Process Code Global Variables Process Heap
Process Resources Open Files Heaps… Environment Block Thread 1 Thread N Thread Local Storage ... Thread Local Storage Stack Stack

7 Threads Performing Parallel Tasks
Single-Threaded Program Multithreaded Program Thread 1 Thread 2 Read File A Read File A Read File B Read File B Wait for Thread 1 and Thread 2 to finish Thread 3 Merge data from both files Merge data from both files Thread 3 Reading File B before File A would give the same results

8 2. Thread Management Creating a Thread The Thread Function
Thread Termination Thread Exit Codes Thread Identities Suspending and Resuming Threads

9 Creating a Thread (1/4) Specify the thread’s start address within the process’ code Specify the stack size, and the stack consumes space within the process’ address space The stack cannot be expanded Specify a pointer to an argument for the thread Can be nearly anything Interpreted by the thread itself CreateThread returns a thread’s ID value and its handle A NULL handle value indicates failure

10 Creating a Thread (2/4) HANDLE CreateThread (
LPSECURITY_ATTRIBUTES lpsa, DWORD cbStack, LPTHREAD_START_ROUTINE lpStartAddr, LPVOID lpvThreadParm, DWORD dwCreate, LPDWORD lpIDThread )

11 Creating a Thread (3/4) Parameters lpsa cbStack lpStartAddr
Security attributes structure (use NULL) cbStack Byte size for the new thread’s stack Use 0 to default to the primary thread’s stack size (1 MB) lpStartAddr Points to the function (within the calling process) to be executed Accepts a single pointer argument and returns a 32-bit DWORD exit code The thread can interpret the argument as a DWORD or a pointer lpThreadParm The pointer passed as the thread argument

12 Creating a Thread (4/4) dwCreate lpIDThread
If zero, the thread is immediately ready to run If CREATE_SUSPENDED, the new thread will be in the suspended state, requiring a ResumeThread function call to move the thread to the ready state lpIDThread Points to a DWORD that receives the new thread’s identifier; NULL OK on W2000/NT

13 The Thread Function DWORD WINAPI MyThreadFunc ( PVOID pThParam )
{ . . . ExitThread (ExitCode); /* OR */ return ExitCode; }

14 Thread Termination (1/2)
Threads are terminated by ExitProcess The process and all its threads terminate The exit code returned by the thread start function same as the process exit code Or a thread can simply return with its exit code ExitThread is the preferred technique The thread’s stack is deallocated on termination VOID ExitThread (DWORD (dwExitCode) When the last thread in a process terminates, so does the process itself

15 Thread Termination (2/2)
You can terminate a different thread with TerminateThread Dangerous: The thread’s stack and other resources will not be deallocated Better to let the thread terminate itself A thread will remain in the system until the last handle to it is closed (using CloseHandle) Then the thread will be deleted Any other thread can retrieve the exit code

16 Thread Exit Codes BOOL GetExitCodeThread ( HANDLE hThread,
LPDWORD lpdwExitCode ) lpdwExitCode Contains the thread’s exit code It could be STILL_ACTIVE

17 Thread Identities A thread has a permanent “ThreadId”
A thread is usually accessed by HANDLE An ID can be converted to a HANDLE HANDLE GetCurrentThread (VOID); DWORD GetCurrentThreadId (VOID); HANDLE OpenThread ( DWORD dwDesiredAccess, BOOL InheritableHandle, DWORD ThreadId ); /* >= Windows 2000 only */

18 Suspend & Resume Threads (1/2)
Every thread has a suspend count A thread can execute only if this count is zero A thread can be created in the suspended state One thread can increment or decrement the suspend count of another: DWORD ResumeThread (HANDLE hThread)

19 Suspend & Resume Threads (2/2)
DWORD SuspendThread (HANDLE hThread) Both functions return previous suspend count 0xFFFFFFFF indicates failure Useful in preventing “race conditions” Do not allow threads to start until initialization is complete Unsafe for general synchronization

20 Waiting for Thread Termination
Wait for a thread to terminate using general purpose wait functions WaitForSingleObject or WaitForMultipleObjects Using thread handles The wait functions wait for the thread handle to become signaled Thread handle is signaled when thread terminates ExitThread and TerminateThread set the object to the signaled state Releasing all other threads waiting on the object ExitProcess sets the process’ state and all its threads’ states to signaled

21 The Wait Functions (1/2) DWORD WaitForSingleObject ( HANDLE hObject,
DWORD dwTimeOut )

22 The Wait Functions (2/2) DWORD WaitForMultipleObjects (
DWORD cObjects, LPHANDLE lphObjects, BOOL fWaitAll, DWORD dwTimeOut ) Return: The cause of the wait completion

23 Wait Options (1/2) Specify either a single handle hObject
Or an array of cObjects referenced by lphObjects cObjects should not exceed MAXIMUM_WAIT_OBJECTS - 64

24 Wait Options (2/2) dwTimeOut is in milliseconds GetExitCodeThread
0 means the function returns immediately after testing the state of the specified objects Use INFINITE for no timeout Wait forever for a thread to terminate GetExitCodeThread Returns the thread exit code

25 Wait Function Return Values (1/2)
fWaitAll If TRUE, wait for all threads to terminate Possible return values are: WAIT_OBJECT_0 The thread terminated (if calling WaitForMultipleObjects; fWaitAll set)

26 Wait Function Return Values (2/2)
WAIT_OBJECT_0 + n where 0 <= n < cObjects Subtract WAIT_OBJECT_0 from the return value to determine which thread terminated when calling WaitForMultipleObjects with fWaitAll set WAIT_TIMEOUT Timeout period elapsed WAIT_ABANDONED Not possible with thread handles WAIT_FAILED Call GetLastError for thread-specific error code

27 The C Library and Threads
Nearly all programs (and thread functions) use the C library But the normal C library is not “thread safe” The C function _beginthreadex has exactly the same parameters as CreateThread

28 Using _beginthreadex Cast the _beginthreadex return value to (HANDLE)
Use _endthreadex in place of ExitThread #include <process.h> Set the multithreaded environment as follows: #define _MT in every source file before <windows.h> Link with LIBCMT.LIB Override the default library Preferred method using Visual C++ From the menu bar: Build Settings — C/C++ Tab Code Generation category Select a multithreaded run-time library

29 Ex: A Simple Boss Thread
HANDLE hWork[K]; volatile LONGLONG WorkDone[K], iTh; /* !! */ . . . for (iTh = 0; iTh < K; iTh++) { WorkDone[ith] = 0; hWork[iTh] = _beginthreadex (NULL, 0, WorkTh, (PVOID)&iTh, 0, NULL); /* BUG! */ } WaitForMultipleObjects (K, hWork, TRUE, INFINITE); for (iTh = 0; iTh < K; iTh++) printf (“Thread %d did %d workunits\n”, iTh, WorkDone[iTh]);

30 Ex: A Simple Worker Thread
DWORD WINAPI WorkTh (PVOID pThNum) { DWORD ThNum = (DWORD)(*pThNum); while (. . .) { /* Perform work */ WorkDone[ThNum]++; } _endthreadex (0);

31 A SYNCHRONIZATION PROBLEM
Thread 1 Thread 2 Running M N Ready 4 M = N; M = M + 1; 4 5 Running Ready 4 5 M = N; M = M + 1; N = M; 5 Running Ready N = M; 5 · · · · · ·

32 2. Thread Synchronization Objects
Known Windows mechanism to synchronize threads: A thread can wait for another to terminate (using ExitThread) by waiting on the thread handle using WaitForSingleObject or WaitForMultipleObjects A process can wait for another process to terminate (ExitProcess) in the same way Other common methods (not covered here): Reading from a pipe or socket that allows one process or thread to wait for another to write to the pipe (socket) File locks are specifically for synchronizing file access

33 Synchronization Objects
Windows provides four other objects specifically designed for thread and process synchronization Three are kernel objects (they have HANDLEs) Events Semaphores Mutexes Many inherently complex problems – beware: Deadlocks Race conditions Missed signals Many more

34 Critical Section Objects
Critical sections Fourth object type can only synchronize threads within a process Often the most efficient choice Apply to many application scenarios “Fast mutexes” Not kernel objects Critical section objects are initialized, not created Deleted, not closed Threads enter and leave critical sections Only 1 thread at a time can be in a specific critical section There is no handle — there is a CRITICAL_SECTION type

35 3. CRITICAL_SECTIONs VOID InitializeCriticalSection (
LPCRITICAL_SECTION lpcsCriticalSection) VOID DeleteCriticalSection ( VOID EnterCriticalSection (

36 CRITICAL_SECTION Management
VOID LeaveCriticalSection ( LPCRITICAL_SECTION lpcsCriticalSection) BOOL TryCriticalSection (

37 CRITICAL_SECTIONS Usage
EnterCriticalSection blocks a thread if another thread is in (“owns”) the section Use TryCriticalSection to avoid blocking A thread can enter a CS more than once (“recursive”) The waiting thread unblocks when the “owning” thread executes LeaveCriticalSection A thread must leave a CS once for every time it entered Common usage: allow threads to access global variables Don’t forget to declare these variables volatile!

38 SYNCHRONIZATION CSs Thread 1 Thread 2 Running M N Idle Idle Running
4 ECS(&CS); M = N; M = M + 1; 4 5 Idle Running ECS(&CS); Running Blocked N = M; 5 LCS (&CS); Running · · · 5 6 M = N; M = M + 1; N = M; 6 LCS(&CS); · · ·

39 CRITICAL_SECTION Comments
CRITICAL_SECTIONS test in user-space Fast – no kernel call But wait in kernel space Usually faster than Mutexes – See Session 3 But, not always Factors include number of threads, number of processors, and amount of thread contention Performance can sometimes be “tuned” Adjust the “spin count” – more later CSs operate using polling and the equivalent of interlocked functions

40 4. Deadlock Example Here is a program defect that could cause a deadlock Some function calls are abbreviated for brevity Aways enter CSs in the same order; leave in reverse order Deadlocks are specific kind of race condition To avoid deadlocks, create a lock hierarchy

41 Deadlock Example CRITICAL_SECTION csM, csN;
volatile DWORD M = 0, N = 0; ... InitializeCriticalSection (&csM); ICS (&csN); DWORD ThreadFunc (...) { ECS (&csM); ECS (&csN); M = ++N; N = M - 2; LCS (&csN); LCS (&csM); M = N--; N = M + 2; }

42 6. Mutexes for Mutual Exclusion
Mutexes can be named and have HANDLEs They are kernel objects They can be used for interprocess synchronization They are owned by a thread rather than a process Threads gain mutex ownership by waiting on mutex handle With WaitForSingleObject or WaitForMultipleObjects Threads release ownership with ReleaseMutex

43 Mutexes (cont’d) Recursive: A thread can acquire a specific mutex several times but must release the mutex the same number of times Can be convenient, for example, with nested transactions You can poll a mutex to avoid blocking A mutex becomes “abandoned” if its owning thread terminates Events and semaphores are the other kernel objects Very similar life cycle and usage

44 Mutexes (cont’d) HANDLE CreateMutex (LPSECURITY_ATTRIBUTES lpsa,
BOOL fInitialOwner, LPCTSTR lpszMutexName) The fInitialOwner flag, if TRUE, gives the calling thread immediate ownership of the new mutex It is overridden if the named mutex already exists lpszMutexName points to a null-terminated pathname Pathnames are case sensitive Mutexes are unnamed if the parameter is NULL

45 Mutexes (cont’d) BOOL ReleaseMutex (HANDLE hMutex)
ReleaseMutex frees a mutex that the calling thread owns Fails if the thread does not own it If a mutex is abandoned, a wait will return WAIT_ABANDONED_0 This is the base value on a wait multiple OpenMutex opens an existing named mutex Allows threads in different processes to synchronize

46 Mutexes (cont’d) Mutex naming:
Name a mutex that is to be used by more than one process Mutexes, semaphores, & events share the same name space Memory mapping objects also use this name space So do waitable timers Not necessary to name a mutex used in a single process

47 Mutexes (cont’d) Process interaction with a named mutex Process 1
h = CreateMutex ("MName"); Process 2 h = OpenMutex ("MName");

48 7. EVENTS (1 of 6) Events can release multiple threads from a wait simultaneously when a single event is signaled A manual-reset event can signal several threads simultaneously and must be reset by the thread An auto-reset event signals a single thread, and the event is reset automatically Signal an event with either PulseEvent or SetEvent Four combinations with very different behavior Be careful! There are numerous subtle problems Recommendation: Only use with SignalObjectAndWait(0) (Much) more on this later – Chapter 9

49 EVENTS (2 of 6) HANDLE CreateEvent ( LPSECURITY_ATTRIBUTES lpsa,
BOOL fManualReset, BOOL fInitialState, LPTCSTR lpszEventName) Manual-reset event: set fManualReset to TRUE Event is initially set to signaled if fInitialState is TRUE Open a named event with OpenEvent Possibly from another process

50 EVENTS (3 of 6) The three functions for controlling events are:
BOOL SetEvent (HANDLE hEvent) BOOL ResetEvent (HANDLE hEvent) BOOL PulseEvent (HANDLE hEvent)

51 EVENTS (4 of 6) A thread signals an event with SetEvent
If the event is auto-reset, a single waiting thread (possibly one of many) will be released The event automatically returns to the non-signaled state If no threads are waiting on the event, it remains in the signaled state until some thread waits on it and is immediately released

52 EVENTS (5 of 6) If the event is manual-reset, the event remains signaled until some thread calls ResetEvent for that event During this time, all waiting threads are released It is possible that other threads will wait, and be released, before the reset PulseEvent allows you to release all threads currently waiting on a manual-reset event The event is then automatically reset

53 EVENTS (6 of 6) When using WaitForMultipleEvents, wait for all events to become signaled A waiting thread will be released only when all events are simultaneously in the signaled state Some signaled events might be released before the thread is released

54 Event Notes Behavior depends on manual or auto reset, Pulse or Set Event All 4 forms are useful AutoReset ManualReset SetEvent Exactly one thread is released. All currently waiting threads If none are currently waiting released. The event remains on the event, the next thread to signaled until reset by some wait will be released. thread. PulseEvent Exactly one thread is released, All currently waiting threads but only if a thread is currently released, and the event is waiting on the event. then reset.

55 8. SEMAPHORES (1 of 4) A semaphore combines event and mutex behavior
Can be emulated with one of each and a counter Semaphores maintain a count No ownership concept The semaphore object is signaled when the count is greater than zero, and the object is not signaled when the count is zero With care, you can achieve mutual exclusion with a semaphore

56 SEMAPHORES (2 of 4) Threads or processes wait in the normal way, using one of the wait functions When a waiting thread is released, the semaphore’s count is incremented by one Any thread can release Not restricted to the thread that “acquired” the semaphore Consider a producer/consumer model to see why

57 SEMAPHORES (3 of 4) HANDLE CreateSemaphore (
LPSECURITY_ATTRIBUTES lpsa, LONG cSemInitial, LONG cSemMax, LPCTSTR lpszSemName) cSemMax is the maximum value for the semaphore Must be one or greater 0 <= cSemInitial <= cSemMax is the initial value You can only decrement the count by one with any given wait operation, but you can release a semaphore and increment its count by any value up to the maximum value

58 SEMAPHORES (4 of 4) BOOL ReleaseSemaphore ( HANDLE hSemaphore,
LONG cReleaseCount, LPLONG lpPreviousCount) You can find the count preceding the release, but the pointer can be NULL if you do not need this value The release count must be greater than zero, but if it would cause the semaphore count to exceed the maximum, the call will return FALSE and the count will remain unchanged There is also an OpenSemaphore function

59 A SEMAPHORE DEADLOCK DEFECT
There is no “atomic” wait for multiple semaphore units But you can release multiple units atomically! Here is a potential deadlock in a thread function for (i = 0; i < NumUnits; i++) WaitForSingleObject (hSem, INFINITE); The solution is to treat the loop as a critical section, guarded by a CRITICAL_SECTION or mutex Or, a multiple wait semaphore can be created with an event, mutex, and counter

60 9. Windows SYNCHRONIZATION OBJECTS
Summary

61 CRITICAL SECTION Named, Securable Synchronization Object
Accessible from Multiple Processes Synchronization Release Ownership Effect of Release No Enter Leave One thread at a time. Recursive One waiting thread can enter

62 MUTEX Named, Securable Synchronization Object
Accessible from Multiple Processes Synchronization Release Ownership Effect of Release Yes Wait Release or owner terminates One thread at a time. Recursive One waiting thread can gain ownership after last release

63 SEMAPHORE Named, Securable Synchronization Object
Accessible from Multiple Processes Synchronization Release Ownership Effect of Release Yes Wait Any thread can release N/A – Many threads at a time, up to the maximum count Multiple threads can proceed, depending on release count

64 EVENT Named, Securable Synchronization Object
Accessible from Multiple Processes Synchronization Release Ownership Effect of Release Yes Wait Set, Pulse N/A – Any thread can Set or Pulse an event One or several waiting threads will proceed after a Set or Pulse - Caution


Download ppt "Windows Thread Management"

Similar presentations


Ads by Google