One 、Linux in Four control methods for process or thread synchronization and mutual exclusion :

1、 A critical region : Access to common resources or a piece of code by serializing multiple threads , Fast , Suitable for controlling data access . 
2、 The mutex : Designed to coordinate common individual access to a shared resource . 
3、 Semaphore : Designed to control a resource with a limited number of users . 
4、 things Pieces of : Used to inform the thread that some events have occurred , So as to start the next task .

Two 、 A critical region (Critical Section

A simple way to ensure that only one thread can access data at any one time . Only one thread is allowed to access shared resources at any time . If there are multiple threads trying to access the critical area at the same time , So there's a line in there After the program enters, all other threads trying to access this critical area will be suspended , And continue until the thread entering the critical area leaves . Critical area after release , Other threads can continue to preempt , And in this way, we can operate in atomic way For the purpose of sharing resources . 
The critical region contains two operation primitives : 
EnterCriticalSection() Enter the critical area  
LeaveCriticalSection() Get out of the critical area  
EnterCriticalSection() After the statement is executed, the code will enter the critical area, no matter what happens , You have to make sure that it matches LeaveCriticalSection() Can be implemented to . Otherwise, the shared resources protected by the critical zone will never be released . Although the synchronization speed in the critical region is very fast , But it can only be used to synchronize this Threads within a process , It can't be used to synchronize threads in multiple processes . 
MFC Provides a lot of fully functional classes , I use MFC The critical region is achieved .MFC There's one for the critical region CCriticalSection class , Using this class for thread synchronization is Very simple . Just use... In the thread function CCriticalSection Class member function Lock() and UnLock() Mark the protected code fragment .Lock() Progeny The resources used by the code are automatically regarded as resources within the critical area and protected .UnLock Only other threads can access these resources . 

3、 ... and 、 The mutex (Mutex) 

The mutex is very similar to the critical region , Only threads with mutexes have access to resources , Because there is only one mutex , Therefore, it is decided that under no circumstances will this shared resource be shared by multiple threads at the same time Visited . The thread that currently occupies the resource should hand over the mutex after the task is processed , So that other threads can access the resource after obtaining it . The mutex is more complex than the critical region . Because using mutex is not only possible in the same Secure resource sharing in different threads of an application , And it can realize the safe sharing of resources among the threads of different applications . 

Mutex contains several operation primitives : 
CreateMutex() Create a mutex  
OpenMutex() Open a mutex  
ReleaseMutex() Release the mutex  
WaitForMultipleObjects() Waiting for mutex object  

Again MFC For mutex, there is a CMutex class . Use CMutex Class to implement the mutex operation is very simple , But pay special attention to CMutex Call the constructor of  
CMutex( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL) 
You can't fill in unnecessary parameters , There will be some unexpected running results if you fill in randomly .

Four 、 Semaphore (Semaphores)

The synchronization of semaphore object to thread is different from the previous methods , Signals allow multiple threads to use shared resources at the same time , It's not the same as... In the operating system PV Same operation . It points to threads that access shared resources at the same time The maximum number . It allows multiple threads to access the same resource at the same time , However, you need to limit the maximum number of threads accessing this resource at any one time . In use CreateSemaphore() Create semaphores The maximum allowed resource count and the current available resource count should be indicated at the same time . Generally, the current available resource count is set to the maximum resource count , Each additional thread has access to shared resources , Current available resource count It will decrease 1, As long as the current available resource count is greater than 0 Of , You can send a semaphore signal . But the current available count is reduced to 0 This indicates that the number of threads currently occupying resources has reached the maximum number allowed , You cannot allow other threads to enter , At this time, the semaphore signal will not be sent out . After the thread has finished processing the shared resources , Should pass at the same time as leaving ReleaseSemaphore() Function will be currently Add... With the resource count 1. At no time can the current available resource count be greater than the maximum resource count . 
PV The concept of operation and semaphore was developed by Dutch scientists E.W.Dijkstra Proposed . Semaphore S It's an integer ,S Greater than or equal to zero represents the number of resource entities that can be used by concurrent processes , but S Less than zero indicates the number of processes waiting to use the shared resource . 
P operation Application resources : 
   (1)S reduce 1; 
   (2) if S reduce 1 After that, it is still greater than or equal to zero , Then the process continues ; 
   (3) if S reduce 1 And then it's less than zero , Then the process is blocked and enters the queue corresponding to the signal , Then go to process scheduling . 
V operation Release resources : 
   (1)S Add 1; 
   (2) If the sum is greater than zero , Then the process continues ; 
   (3) If the sum is less than or equal to zero , Then wake up a waiting process from the waiting queue of the signal , Then return to the original process to continue execution or transfer to process scheduling . 
   Semaphores contain several operation primitives : 
   CreateSemaphore() Create a semaphore  
   OpenSemaphore() Turn on a semaphore  
   ReleaseSemaphore() Release semaphore  
   WaitForSingleObject() Wait for the semaphore  

5、 ... and 、 event (Event)   

Event objects can also keep threads synchronized by notification operations . And it can realize the synchronous operation of threads in different processes . 
Semaphores contain several operation primitives : 
   CreateEvent() Create a semaphore  
   OpenEvent() Open an event  
   SetEvent() Reset event  
   WaitForSingleObject() Waiting for an event  
   WaitForMultipleObjects() Waiting for multiple events  
   WaitForMultipleObjects The function prototype : 
   IN DWORD nCount, // Number of waiting handles  
   IN CONST HANDLE *lpHandles, // Points to an array of handles  
   IN BOOL bWaitAll, // Whether to wait for the sign completely  
   IN DWORD dwMilliseconds // Waiting time  
Parameters nCount Specifies the number of kernel objects to wait for , The array of these kernel objects is created by lpHandles Point to .fWaitAll For the designated nCount Kernel Two waiting modes of the object are specified , by TRUE When all objects are notified, the function returns , by FALSE Then as long as any one of them is notified, they can return . dwMilliseconds The role here and in WaitForSingleObject() It's the same thing . If the wait times out , Function will return WAIT_TIMEOUT.

6、 ... and 、 summary : 
1. The function of mutual exclusion is very similar to that of critical region , But mutex can be named , In other words, it can be used across processes . So creating mutex requires more resources , So if it's only for use inside the process, make Using critical area will bring speed advantage and reduce resource consumption . Because mutex is a cross process mutex, once created , You can open it by name . 
2. The mutex (Mutex), Signal lamp (Semaphore), event (Event) Can be used across processes to synchronize data operations , Other objects have nothing to do with data synchronization , but For processes and threads , If the process and thread are running, they are in a no signal state , It is signaled after exit . So you can use WaitForSingleObject To wait for the process and Thread to exit . 
3. Through mutex, you can specify that resources are used exclusively , But if there is one of the following situations, it can't be handled through mutex , For example, now a user has purchased a database system with three concurrent access licenses , Can root The number of threads depends on the number of access licenses purchased by the user / The process can operate the database at the same time , At this time, there is no way to complete this requirement by using mutex , A semaphore object can be said to be a resource count device .