We have already introduced how to determine whether a thread is terminated during thread creation and destruction. However, a challenging problem for writing a multi-threaded program is how to make a thread cooperate with another thread. There will be multiple threads in the same time period. When these threads simultaneously access the same data, there will be problems. Just like storing items in a supermarket, the item box is empty when it comes, and when it turns to prepare the item for storage, it is found that the item box has been occupied. At this time, the item box is the same data as I said, and the person refers to the thread. The coordination between threads is completed by Synchronous Machines. The synchronization mechanism is equivalent to the traffic light system between threads. It is responsible for giving a thread a green light and waiting for other threads a red light. Note: To describe synchronous and Asynchronization, the so-called synchronization: When program 1 calls Program 2, program 1 does not stop until Program 2 completes and returns to program 1, program 1 will continue. In Win32 API, SendMessage () is a synchronous action, while PostMessage () is an asynchronous action. Now, let's look at the first synchronization mechanism. I. Critical Sections (Critical region and key region) main operations include InitializeCriticalSection EnterCriticalSection LeaveCriticalSection ecriticalsection. An example is provided to illustrate: [cpp] CRITICAL_SECTION gBoxKey; DWORD WINAPI ThreadFun) {// enter the key area (scenario: Close the item box and dial the key) EnterCreiticalSection (& gBoxKey); // () // process some operations that are inseparable ..... // (Scene: Turn around and take items, store items, and go shopping ....) // Leave the key area (scenario: Open the inventory box, take out the stored items, and insert the key) LeaveCreiticalSection (& gBoxKey); // ()} void main () {// initialize the global lock (scenario: the Key to generate the item box) InitializeCriticalSection (& gBoxKey); // generate two threads (scenario: Prepare two people to grab one item box) HANDLE hMan1 = CreateThread (NULL, 0, ThreadFun ,......); HANDLE hMan2 = CreateThread (NULL, 0, ThreadFun ,......); CloseHandle (hMan1); CloseHandle (hMan2); // Delete the global lock (scenario: Delete the key of the item box) DeleteCriticalSection (& gBoxKey);} note: 1. Once a thread enters a critical section, it can repeatedly enter the critical section, but every time it enters a corresponding exit; 2. It is difficult to define the minimum lock time, if the resource is locked all the time, you will stop the execution of other threads, so do not call Sleep () or any Wait function in the critical section. When using the critical area, the deadlock problem may occur when two threads wait for each other's resources to form a waiting cycle. This situation is called a "deadlock ". The following describes the causes of deadlocks. The cause of the deadlock is as follows: (1) Insufficient system resources. (2) The order in which the process is promoted is inappropriate. (3) improper resource allocation. Four Conditions for deadlock: (1) mutex conditions: a resource can only be used by one process at a time. (2) request and retention conditions: when a process is blocked by requesting resources, it will not release the obtained resources. (3) Non-deprivation condition: the resources obtained by the process cannot be forcibly deprived before they are used. (4) Cyclic waiting condition: a cyclic waiting resource relationship is formed between several processes that are connected at the beginning and end. Avoid deadlock: the prevention of deadlocks is to prevent the occurrence of deadlocks by damaging the conditions, but this method damages the concurrency and concurrency of the system. The first three conditions of a deadlock are necessary conditions for the deadlock to be generated. That is to say, the conditions that must be met for the deadlock to be generated, instead of the three conditions, the deadlock must be generated, so long as the fourth condition is avoided logically, the deadlock can be avoided. To avoid deadlocks, the first three conditions are allowed, but a reasonable resource allocation algorithm is used to ensure that the closed process chain of loop wait will never be formed to avoid deadlocks. This method supports parallel execution of multiple processes. To avoid deadlocks, the system dynamically determines whether to allocate a resource to the requested process. Deadlock Prevention: the specific approach is to destroy one of the four necessary conditions for deadlock. 2. Mutexes (mutex) only one thread can own mutex within a time period, just as one thread can only enter the same Critical Section within a time period. There is almost no difference between Mutexes and Critical Sections, regardless of the idea of sharing resources or programming code. Of course, there are some differences between mutex and critical section: 1. Locking an unowned mutex takes almost 100 times to lock an unowned critical section. 2. mutex can be used across processes, the critical section can only be used in the same process. 3. When waiting for a mutex, you can specify the duration of the "end wait, this avoids the issue of logging in the lock process (which is described below ). Raise the question: the mechanism of Mutexes must be raised for some reason. Let's look at this situation. When I take the key away, I can no longer come back because of some factors, this box can no longer be used. That is to say, if the Critical Sections thread is dropped halfway, the other thread will no longer be able to enter the Critical Sections (a resource is wasted ), the threads that need to enter the Critical Sections will stop at the entry and will never end. Solution: Do you still remember the WaitForSingleObject learned in the previous chapter? The previous chapter mainly used it to wait for the end of the thread, but this function is not limited to this. Here, we will take a small step to explore the wonderful use of the WaitForSingleObject function. Here, I met a core object called mutex, which defines the excitation as: "When no thread owns the mutex, and a thread is running with Wait... () Wait for the mutex, And the mutex will be excited for a short time, so that Wait... () Can be returned, so in other cases, mutex is in the not activated state ". Well, we have a better understanding of the WaitForSingleObject function. So, how can we solve the problems caused by Critical Sections? When ReleaseMutex is not called before the thread with mutex ends (whether the thread is used or the ReleaseMutex is forgotten), the other threads are waiting for singleobject () wait for the mutex thread to receive WAIT_ABANDONED_0. With this value, I can solve the problem. Example: [cpp] HANDLE hBoxKey; dword winapi ThreadFun (LPVOID n) {// enter the key area (scenario: Close the inventory box and dial the key) WaitForSingleObject (hMutex, INFINITE ); //// process some inseparable operations ..... // (Scene: Turn around and take items, store items, and go shopping ....) // Exit the key area (scenario: Open the inventory box, take out the stored items, and insert the key) ReleaseMutex (hMutex); //} void main () {// initialize the global lock (scenario: hBoxKey = CreateMutex (NULL, FALSE, NULL); // generate two threads (scenario: Prepare two people to grab one bin) HANDLE hMan1 = CreateThread (NULL, 0, threadFun ,......); HANDLE hMan2 = CreateThread (NULL, 0, ThreadFun ,......); CloseHandle (hMan1); CloseHandle (hMan2); // Delete the global lock (scenario: Delete the key of the item box) CloseHandle (hBoxKey );}