I. What is the "abandonment" problem
In the seventh chapter, the mutex can handle the "abandonment" problem, the following text is quoted:
Mutexes are often used for thread mutexes between multiple processes, so it has a more useful feature than critical segments-the handling of " abandonment " situations. For example, if a thread that occupies a mutex terminates unexpectedly before calling ReleaseMutex () to trigger a mutex (equivalent to the mutex being "abandoned"), will all threads waiting for this mutex be caught in an infinite wait process because the mutex cannot be triggered? This is obviously unreasonable. Since the thread that occupies a mutex is terminated, it is sufficient to prove that it is no longer using the resources protected by the mutex, so these resources are fully and should be used by other threads. Therefore, in this " abandonment " case, the system automatically sets the internal thread ID of the mutex to 0, and its recursive counter is reset to 0, indicating that the mutex is triggered. Then the system will "fairly" select a waiting thread to complete the Dispatch (WaitForSingleObject () of the selected thread will return WAIT_ABANDONED_0).
The problem with "abandonment" can be seen--whether the process of owning a resource terminates unexpectedly and the other processes waiting for that resource are aware.
Two "Abandonment" Issues in key sections
Critical segments are simple on this issue-because critical segments cannot be used across processes, critical segments do not need to deal with "abandonment" issues.
Three event, mutex, semaphore "abandonment" problem
Events, mutexes, semaphores are kernel objects that can be used across processes. After a process creates a named event, other processes can call OpenEvent () and pass in the name of the event to get a handle to the event. So events, mutexes, and semaphores all encounter "abandonment" issues. We already know that mutexes can handle "abandonment", and then we'll look at whether events and semaphores can handle "abandonment" issues. Similar to the seventh experiment on mutexes, the following also tests the events and semaphores:
1. Create two processes.
2. Process one creates an event that is initially not triggered and then waits for the key, pressing Y to end the process after the event is triggered, or a direct exit to indicate that the process has terminated unexpectedly.
3. The process two obtains the handle of the event first, then calls WaitForSingleObject () to wait for this event for 10 seconds, in which case the output "received signal" if the event has already been triggered, otherwise the output "does not receive a signal within the specified time". If the process terminates unexpectedly during the wait, the output "the process that owns the event terminates unexpectedly". The signal volume is tested in a similar way.
To enhance the contrast, the test results of the mutex are shown first (see the seventh article for code)
It can be seen that the second process that waits for this mutex is able to perceive the unexpected termination of a process when the first process exits without triggering the mutex.
The next step is to complete the "abandonment" problem test code for the event.
Process one:
[CPP]View PlainCopy
- #include <stdio.h>
- #include <conio.h>
- #include <windows.h>
- Const TCHAR str_event_name[] = TEXT ("event_morewindows");
- int main ()
- {
- printf ("The abandonment process for classic thread synchronization events is a \ n");
- printf ("-by Morewindows (http://blog.csdn.net/MoreWindows)--\n\n");
- HANDLE hevent = CreateEvent (NULL, False, False, Str_event_name); //Auto position not currently triggered
- printf ("event has been created, now press Y to trigger the event, press other key to terminate the process \ n");
- Char ch;
- scanf ("%c", &ch);
- if (ch! = ' y ')
- Exit (0); //Indicates that the process terminated unexpectedly
- SetEvent (hevent);
- printf ("event has been triggered \ n");
- CloseHandle (hevent);
- return 0;
- }
Process two:
[CPP]View PlainCopy
- #include <stdio.h>
- #include <windows.h>
- Const TCHAR str_event_name[] = TEXT ("event_morewindows");
- int main ()
- {
- printf ("The abandonment process for classic thread synchronization events two \ n");
- printf ("-by Morewindows (http://blog.csdn.net/MoreWindows)--\n\n");
- HANDLE hevent = OpenEvent (event_all_access, TRUE, str_event_name); //Open Event
- if (hevent = = NULL)
- {
- printf ("Open event failed \ n");
- return 0;
- }
- printf ("waiting .... \ n");
- DWORD dwresult = WaitForSingleObject (hevent, 10 * 1000); //Wait for event to be triggered
- switch (dwresult)
- {
- Case wait_abandoned:
- printf ("The process that owns the event terminated unexpectedly \ n");
- Break ;
- Case WAIT_OBJECT_0:
- printf ("The signal has been received \ n");
- Break ;
- Case Wait_timeout:
- printf ("no signal received within the specified time \ n");
- Break ;
- }
- CloseHandle (hevent);
- return 0;
- }
Event events test Result 1-normal end after a trigger event for a process:
Event Events Test Result 2-process an unexpected termination:
It can be seen that process two failed to perceive the unexpected termination of the process, stating that the event could not handle the "abandonment" issue.
Let's try the semaphore again below.
The "abandonment" problem test code for the semaphore:
Process one:
[CPP]View PlainCopy
- #include <stdio.h>
- #include <conio.h>
- #include <windows.h>
- Const TCHAR str_semaphore_name[] = TEXT ("semaphore_morewindows");
- int main ()
- {
- printf ("Classic thread synchronous semaphore abandonment process one \ n");
- printf ("-by Morewindows (http://blog.csdn.net/MoreWindows)--\n\n");
- HANDLE Hsemaphore = CreateSemaphore (NULL, 0, 1, str_semaphore_name); //Current 0 resources, maximum allowed 1 simultaneous access
- printf ("Semaphore has been created, now press Y to trigger the semaphore, press other key to terminate the process \ n");
- Char ch;
- scanf ("%c", &ch);
- if (ch! = ' y ')
- Exit (0); //Indicates that the process terminated unexpectedly
- ReleaseSemaphore (Hsemaphore, 1, NULL);
- printf ("The semaphore has been triggered \ n");
- CloseHandle (Hsemaphore);
- return 0;
- }
Process two:
[CPP]View PlainCopy
- #include <stdio.h>
- #include <windows.h>
- Const TCHAR str_semaphore_name[] = TEXT ("semaphore_morewindows");
- int main ()
- {
- printf ("Classic thread synchronous semaphore of abandonment process two \ n");
- printf ("-by Morewindows (http://blog.csdn.net/MoreWindows)--\n\n");
- HANDLE Hsemaphore = OpenSemaphore (semaphore_all_access, TRUE, str_semaphore_name); //Open signal Volume
- if (Hsemaphore = = NULL)
- {
- printf ("Open semaphore failed \ n");
- return 0;
- }
- printf ("waiting .... \ n");
- DWORD dwresult = WaitForSingleObject (Hsemaphore, 10 * 1000); //wait for the semaphore to be triggered
- switch (dwresult)
- {
- Case wait_abandoned:
- printf ("The process with semaphore has terminated unexpectedly \ n");
- Break ;
- Case WAIT_OBJECT_0:
- printf ("The signal has been received \ n");
- Break ;
- Case Wait_timeout:
- printf ("no signal received within the specified time \ n");
- Break ;
- }
- CloseHandle (Hsemaphore);
- return 0;
- }
Semaphore semaphore test Result 1-normal end of process one trigger semaphore
Semaphore semaphore test Result 2-process an unexpected termination
It can be seen that process two failed to perceive the process of an unexpected termination, indicating that the semaphore and the event can not deal with the "abandonment" problem.
Four Summary of the "abandonment" problem
The experiment in this paper shows that the mutex can deal with the situation of "abandonment", and the event and Semaphore cannot solve the situation.
The reason why the mutex can deal with the "abandonment" problem is that it has the concept of "thread ownership". In the system, once the thread end, the system will determine whether there is a mutex is occupied by the threads, if there is, the system will be the mutex object inside the thread ID number will be set to NULL, the recursive count is set to 0, which means that the mutex is no longer occupied by any thread, is in the trigger state. Other threads waiting for this mutex will be able to execute smoothly. As to how threads get Mutex "thread ownership", the MSDN description for--a thread obtainsownership of A mutex either by creating it with the BinitialownerPA Rameter set to TRUE or by specifying it handle in a call toone of the wait functions.
Multi-threaded Face Question series (15): Key segment, event, mutex, semaphore "abandonment" problem