This series is intended to record the knowledge points of windwos threads, including thread basics, thread scheduling, thread synchronization, TLS, and thread pool.
Use kernel objects for Thread Synchronization
Kernel objects: Windows operating systems use kernel objects to manage a large number of resources of processes, threads, files, and other types. The kernel object is usually created through a Windows API. For example, createthread creates a thread Kernel Object and returns a kernel object handle. The kernel object is actually a small piece of memory, which includes reference counting, security descriptions, and other information. The operating system manages the corresponding kernel resources through this small segment of memory. The actual memory address of the kernel object is not displayed by the handle. They are mapped to the kernel object handle table in the process.
In the previous articles, we introduced the thread synchronization mechanism in user mode: interlocked series, key segments, and slim read/write locks. These synchronization mechanisms can keep threads in user mode while synchronizing threads. However, the thread synchronization mechanism in user mode sometimes cannot meet our requirements. Starting from this article, we will introduce how to use kernel objects for thread synchronization. When considering whether to use the synchronization mechanism in user mode or the kernel object for synchronization, we need to make full use of the thread synchronization mechanism in user mode.
Kernel objects generally exist in two states: trigger or not trigger. Each kernel object has its own special characteristics in the switching process between these two States. For example, when a process kernel object is created, it is always in the not triggered state. when the process is terminated, will change to the trigger state, and the process kernel object will never change from the trigger state to the trigger state. Therefore, if our thread needs to wait until the sub-process is terminated, it can enter the waiting state. When the process Kernel Object identified by the sub-process changes to the triggered state, it will wake up the thread! All we need is the waiting function provided by windows.
Wait Function
The waiting function can be a thread that enters the waiting state until the specified kernel object is triggered. These wait functions are:
DWORD winapi waitforsingleobject (_ in handle hhandle, _ in DWORD dwmilliseconds );
When a thread calls waitforsingleobject, the first parameter hobject is used to identify the kernel object, and the second parameter is a time-out period (infinite is passed in to indicate waiting forever until it is triggered ).
DWORD winapi waitformultipleobjects (_ in DWORD ncount, _ in const handle * lphandles, _ in bool bwaitall, _ in DWORD dwmilliseconds );
Waitformultipleobjects allows the calling thread to check the trigger status of Multiple kernel objects.
Using the wait function sometimes changes the state of the kernel object. For example, the thread is waiting for an automatic reset event object. When the event object is triggered, the function will detect this situation and return the call thread, but before returning, it changes the event to a non-trigger state. Wait for the function to be called on different kernel objects and return such similar "side effects. After introducing the kernel object, you will see this.
If multiple threads wait for the same kernel object at the same time, any thread may be awakened. We should not make assumptions like "wake up when waiting first.
Next, we will introduce the kernel objects related to thread synchronization in several articles.
Event Kernel Object
The event kernel objects are divided into manual resetting and automatic resetting. The difference is that when the object is not triggered and changes to the trigger state, it will not be automatically reset back to the trigger state. Like other kernel objects, event kernel objects include reference counts. The following createevent function is used to create an event kernel object:
Handle createevent (lpsecurity_attributes lpeventattributes, bool bmanualreset, bool binitialstate, lptstr lpname );
Lpeventattributes: ignored, must be null (here is the msdn statement, in Windows via C/C ++, it implies that this parameter is related to the security attribute and sharing feature of the kernel object. However, null is usually passed in, because it does not take into account changing an event object to an inherited one)
Bmanualreset: manual reset (true) or automatic reset (false)
Binitialstate: whether the initial state is trigger (true) or non-trigger (false)
Lpname: used to share the kernel object mechanism. This mechanism is irrelevant to thread synchronization. You can pass in null.
Return Value: handle of the event object
Windows Vista also supports the following function createeventex to create event kernel objects. For details, see msdn:
Handle winapi createeventex (_ in_opt lpsecurity_attributes lpeventattributes, _ in_opt lptstr lpname, _ in DWORD dwflags, _ in DWORD dwdesiredaccess );
We use the following function to control the state of the event object:
Bool setevent (handle hevent); // set the kernel object to the trigger state bool resetevent (handle hevent); // set the kernel object to the non-trigger state bool pulseevent (handle hevent ); // trigger the kernel object and reset it to the untriggered state, which will wake up the waiting thread
It would be intuitive to use graphs to represent their functions:
In addition, openevent is usually used for process synchronization, provided that the event kernel object must have an alias (by alias certain kernel objects, it is a way to share kernel objects ):
Handle openevent (DWORD dwdesiredaccess, bool binherithandle, lpctstr lpname );
Describes the sample usage of the event Kernel Object (within the same process ):
The main thread first creates an event Kernel Object and creates two threads. The execution of these two threads depends on the preparation of the main thread. Therefore, waitforsingleobject is called to wait for the event object to be triggered. After the main thread completes the preparation, call setevent to trigger the object. Then, the two subthreads will be awakened and started to execute.Code.
In the subsequent sections, we will continue to introduce other kernel objects that can be used for thread synchronization.
Labor fruit, reproduced please indicate the source: http://www.cnblogs.com/P_Chou/archive/2012/07/03/waitobject-and-event-in-thread-sync.html