When multiple threads access a shared resource or data at the same time, you need to consider thread synchronization, Synchronize () is running in a hidden window, if your task is busy here, your main window will block out, and Synchronize () just put the thread's code in the main thread and run it. Not thread synchronization. The critical section is the best way to synchronize all threads in a process, he is not system-level, only process-level, that is, he may use some of the process of flags to ensure that the process of thread synchronization, according to Richter is a counting cycle; critical sections can only be used within the same process; critical sections can wait indefinitely. However 2k added the TryEnterCriticalSection function to achieve 0 time waits. Mutual exclusion is to ensure the synchronization of threads between multiple processes, he uses the system kernel objects to ensure synchronization. Because system kernel objects can have names, multiple processes can take advantage of this named kernel object to ensure thread safety of system resources. The mutex is the Win32 kernel object, which is managed by the operating system, and the mutex can use WaitForSingleObject to achieve infinite wait, 0 time waits and any time waits. The common thread synchronization methods are as follows:
1. Critical section
A critical section is the most straightforward way to synchronize threads. The so-called critical section is a piece of code that can be executed by only one thread at a time. If the code that initializes the array is placed in the critical section, the other thread will not be executed until the first thread has finished processing. Here's how to use it:
In form creation
InitializeCriticalSection (CRITICAL1)
In the form of destruction
DeleteCriticalSection (CRITICAL1)
Threads in the thread
EnterCriticalSection (CRITICAL1)
...... Code to protect
LeaveCriticalSection (CRITICAL1)
2. Mutex
Mutexes are very similar to critical sections, except for the two key differences: First, mutexes can be used to synchronize threads across processes. Second, the mutex can be given a string name, and an additional handle to the existing mutex is created by referencing the name. The biggest difference between a critical section and an event object, such as a mutex, is performance. When there is no thread conflict, the critical section uses 10 ~ 15 time slices, and the event object has to use 400~600 time slices because of the system kernel involved.
A mutex (mutex object), which is a global object used to serialize access to a resource. We first set up the mutex object, then access the resource and finally release the mutex object. When a mutex is set, if another thread (or process) attempts to set the same mutex object, the thread will stop until the previous thread (or process) releases the mutex. Note that it can be shared by different applications. Here's how to use it:
In form creation
Hmutex:=createmutex (Nil,false,nil)
In the form of destruction
CloseHandle (Hmutex)
Threads in the thread
WaitForSingleObject (Hmutex,infinite)
...... Code to protect
ReleaseMutex (Hmutex)
3. Signal Volume
Another technique for synchronizing threads is to use semaphore objects. It is built on the basis of mutual exclusion, but the semaphore increases the function of the resource count, and a predetermined number of threads allow simultaneous access to the code to be synchronized. You can use CreateSemaphore () to create a semaphore object, because only one thread is allowed to enter the code to be synchronized, so the maximum semaphore count value (lMaximumCount) is set to 1. In fact, the mutex is the maximum count of one semaphore. Here's how to use it:
In form creation
hsemaphore:= CreateSemaphore (Nil,linitialcount,lmaximumcount,lpname)
In the form of destruction
CloseHandle (Hsemaphore)
Threads in the thread
WaitForSingleObject (Hsemaphore,infinite)
...... Code to protect
ReleaseSemaphore (Hsemaphore, lReleaseCount, Lppreviouscount)
The return value of the 4.WaitForSingleObject function:
The object specified by Wait_abandoned is a mutex object, and the thread that owns the mutex terminates before the object is disposed of. At this point, the mutex object is called discarded. In this case, the mutex is owned by the current thread and is set to a non-signaled state;
WAIT_OBJECT_0 the specified object is in signaled state;
Wait_timeout wait time has been over, the object is still non-signaled state;
Delphi commonly used critical section object Tcriticalsection (Delphi), Trtlcriticalsection
Trtlcriticalsection is a struct, defined in a Windows cell; Initializecriticalsection,entercriticalsection,leavecriticalsection, DeleteCriticalSection the parameters of the critical section operation API in these Kernel32.dll;
Tcriticalsection is the class implemented in the SYNCOBJS unit, which encapsulates the above critical section operation API functions, simplifies and facilitates the use of Delphi, such as Tcriticalsection.create, Tcriticalsection.enter, Tcriticalsection.leave, etc., by invoking the API function of the response above.
The simplest and most efficient way to use a critical section is in many ways of thread synchronization (minimum CPU time)
Use the critical section code as follows:
Declare a global variable of type trtlcriticalsection first
Var
Mycs:trtlcriticalsection;
Before the program starts or creates a thread, initialize the
InitializeCriticalSection (MYCS);//Initialize critical section
After the program ends or all threads end, delete it
DeleteCriticalSection (MYCS);//Delete critical section
Then join in the thread where you want to synchronize
EnterCriticalSection (MYCS); Enter the critical section
Try
Program code
Finally
LeaveCriticalSection (MYCS); Leave the critical section
End
Add a question about Application.processmessages synchronization today: There is a function that FN can be divided into a->b->c 3 chunks in order of execution, where B blocks have a complex and lengthy operation to draw various window interfaces. And it uses the Application.processmessages, the program runs the test found that if the FN execution of the B drawing window is not finished, and then call the FN function to draw other windows can cause the program to crash, The first attempt to solve with the tcriticalsection variable is completely useless, and finally solved by adding a global variable: Define a Global Boolean flag, set the initial value to true, and transform the FN function to a-> if flag then
Begin
Flag:=false;
B
Flag:=true;
End;
->c
Problem solved successfully.
By the way, summarize the role of Application.processmessages: Run a very time-consuming cycle, then at the end of this cycle, the program may not respond to any events, the button does not respond, the program settings cannot draw the form, it looks like dead, this is sometimes not very convenient, such as the opportunity to terminate the loop is not With, and do not want to use multi-threading, then you can add such a sentence in the loop, each time the program runs to this sentence, the program will let the system respond to the message, so that you have the opportunity to press the button, the form has the opportunity to draw. The function is similar to the Doevent method in VB. Calling ProcessMessages enables the application to be in Message Queuing for message processing, processmessages Windows messages to rotate until the message is empty, and then returns control to the application.
Note: Do not slightly message process effects when the application calls ProcessMessages, not in other applications. In lengthy operations, calling ProcessMessages periodically causes the application to respond to brushes or other information. ProcessMessages do not allow the program to be idle, and handlemessage. Use processmessages must ensure that the relevant code is reentrant, if not really can also be implemented in accordance with my method of synchronization.
Delphi Synchronization Mutual Exclusion Summary