It’s a concept that was introduced with the win32 style of application coding,
which allows multiple threads to run at the same time in a process or
application. The concurrent execution can be on different processors or in the
same processor in a time sliced manner.
Each thread has its own stack and its own copy of the CPU registers. Other
resources of the process are shared by all threads and while trying to access
them it should be synchronized. Win32 provides a number of synchronization
methods like
1. Semaphores
2. Critical section
3. Events
4. Mutexes
These objects are either in the signaled or non-signaled state. By specifying
the handle to any of these objects in a call to one of the wait functions would
block the execution of the calling thread until the state of the specified
object is signaled. This is different in case of a critical section we use the
EnterCriticalSection to get hold of a critical section object. Some of
the wait functions used in the above case is
1. WaitforSingleObject (single-object wait functions)
2. WaitForMultipleObject (multiple-object wait functions)
3. SignalObjectAndWait (Alertable wait functions)
4. RegisterWaitForSingleObject (Registered wait functions)
The synchronization is needed for globally shared resources or data. And it is
advisable to use global data only in time of need. We can make use of the
Threads Local Storage capabilities to store per-thread data. And there are some
TLS API (Tlsalloc, TlsGetValue, TlsSetValue and TlsFree) to access
these information.
When a new thread is created, a handle to the thread is returned. And it is
valid until closed, even after the thread it represents has been terminated. The
handle can be duplicated with the DuplicateHandle API.
A thread also contains a thread ID which is unique to the thread and can be
accessed using the API GetCurrentThreadID. It is important to note that
no thread identifier will have a value 0 and is valid only until the thread is
terminated. We could get a thread handle using the OpenThread API, if we
are in possession of the thread identifier.
A thread can suspend and resume its execution using the SuspendThread and
ResumeThread APIs. Sleep or SleepEx are used to delay the
execution of a thread for a specified interval of time.
|