Two multithread synchronization methods are available:
Criticalsection (critical section) and mutex (mutex). The two Synchronization Methods are similar, but they have different scopes;
The criticalsection is similar to a public restroom with only one squatting position and can only be entered one by one;
Mutex (mutex) objects are similar to the baton in a race. They can only be held by one person at a time.
What is semaphore?
For example, if you have to go to a bank or buy a ticket at the station, there is only one waiter. No matter how many people are waiting in queue, the business can only come one by one.
If a business window is added, how many businesses can be accepted at the same time?
This is similar to the semaphore object. semaphore can process several threads simultaneously applied by waiting functions (such as waitforsingleobject.
Semaphore works as follows:
1. First, you must use createsemaphore (Security Settings, initial signal count, total signal count, and signal name) to create a signal object;
Parameter 4: Like mutex, it can have a name or no name. In this example, there is no name (nil). A name is generally used across processes.
Parameter 3: Total number of signals, which is the maximum processing capability of semaphore, just like how many business windows a bank has;
Parameter 2: initial signal count, which is like a bank's business window, but opening a few is not necessarily the same if it is not opened;
Parameter 1: The security settings are the same as the preceding ones. Use the default value (nil.
2. To accept the thread of the semaphore service (or called coordination), you also need to queue for the waiting function (such as waitforsingleobject;
3. When a thread uses a signal, releasesemaphore (signal handle, 1, nil) should be used to give available signals to other threads;
Parameter 3: generally nil. If a numeric pointer is given, the total number of idle signals at this time (Before) can be received;
Parameter 2: generally 1, indicating that an available signal is added;
If you want to increase the initial signal for createsemaphore, you can also use releasesemaphore.
4. Use closehandle as the system kernel object.
In addition, when the total number of semaphore is 1, it is the same as mutex (mutex.
In this example, each button is clicked to create a signal object with a total of 5 signals. The initial signal comes from edit1, and five threads queue at the same time.
The example of tsemaphore in Delphi is also attached in this example, but it has not been entangled in many details, so as to get the overall idea of multithreading as soon as possible.
In this example:
Code File:
Unit unit1; interfaceuses windows, messages, sysutils, variants, classes, graphics, controls, forms, dialogs, stdctrls; Type tform1 = Class (tform) button1: tbutton; edit1: tedit; procedure button1click (Sender: tobject); Procedure upload (Sender: tobject); Procedure formdestroy (Sender: tobject); Procedure edit1keypress (Sender: tobject; var key: Char); end; vaR form1: tform1; implementation {$ R *. DFM} var F: integer; {coordinate the output location of each thread with this variable} hsemaphore: thandle; {handle of the signal object} function mythreadfun (P: pointer): DWORD; stdcall; var I, Y: integer; begin Inc (f); y: = 20 * F; If waitforsingleobject (hsemaphore, infinite) = wait_object_0 then begin for I: = 0 to 1000 do begin form1.canvas. lock; form1.canvas. textout (20, Y, inttostr (I); form1.canvas. unlock; sleep (1); {so that the canvas is too busy} end; releasesemaphore (hsemaphore, 1, nil); Result: = 0; end; Procedure tform1.button1click (Sender: tobject); var threadid: DWORD; begin {I don't know if I have created a semaphore object before. If I close} closehandle (hsemaphore); {create semaphore object} hsemaphore: = createsemaphore, strtoint (edit1.text), 5, nil); self. repaint; F: = 0; createthread (nil, 0, @ mythreadfun, nil, 0, threadid); createthread (nil, 0, @ mythreadfun, nil, 0, threadid ); createthread (nil, 0, @ mythreadfun, nil, 0, threadid); createthread (nil, 0, @ mythreadfun, nil, 0, threadid); createthread (nil, 0, @ mythreadfun, nil, 0, threadid); end; {allow Edit to accept only 1 2 3 4 5 5 count} procedure tform1.edit1keypress (Sender: tobject; var key: Char ); begin if not charinset (Key, ['1 '.. '5']) then key: = #0; end; Procedure tform1.formcreate (Sender: tobject); begin edit1.text: = '1'; end; Procedure tform1.formdestroy (Sender: tobject ); begin closehandle (hsemaphore); end.
Form file:
Object form1: tform1 left = 0 Top = 0 caption = 'form1' clientheight = 140 clientwidth = 192 color = clbtnface font. charset = default_charset font. color = clwindowtext font. height =-11 font. name = 'tahoma 'font. style = [] oldcreateorder = false oncreate = formcreate pixelsperinch = 96 textheight = 13 object button1: tbutton left = 109 Top = 107 width = 75 Height = 25 caption = 'button1' taborder = 0 onclick = button1click end object edit1: tedit left = 109 Top = 80 width = 75 Height = 21 taborder = 1 text = 'edit1' onkeypress = edit1keypress endend
Use the tsemaphore class under the syncobjs unit for implementation. The method is similar and the running effect is the same:
Unit unit1; interfaceuses windows, messages, sysutils, variants, classes, graphics, controls, forms, dialogs, stdctrls; Type tform1 = Class (tform) button1: tbutton; edit1: tedit; procedure button1click (Sender: tobject); Procedure upload (Sender: tobject); Procedure formdestroy (Sender: tobject); Procedure edit1keypress (Sender: tobject; var key: Char); end; vaR form1: tform1; implementation {$ R *. DFM} uses syncobjs; var F: integer; mysemaphore: tsemaphore; function mythreadfun (P: pointer): DWORD; stdcall; var I, Y: integer; begin Inc (f ); y: = 20 * F; If mysemaphore. waitfor (infinite) = wrsignaled then begin for I: = 0 to 1000 do begin form1.canvas. lock; form1.canvas. textout (20, Y, inttostr (I); form1.canvas. unlock; sleep (1); end; mysemaphore. release; Result: = 0; end; Procedure tform1.button1click (Sender: tobject); var threadid: DWORD; begin if assigned (mysemaphore) Then mysemaphore. free; mysemaphore: = tsemaphore. create (nil, strtoint (edit1.text), 5, ''); self. repaint; F: = 0; createthread (nil, 0, @ mythreadfun, nil, 0, threadid); createthread (nil, 0, @ mythreadfun, nil, 0, threadid ); createthread (nil, 0, @ mythreadfun, nil, 0, threadid); createthread (nil, 0, @ mythreadfun, nil, 0, threadid); createthread (nil, 0, @ mythreadfun, nil, 0, threadid); end; {allow Edit to accept only 1 2 3 4 5 5 count} procedure tform1.edit1keypress (Sender: tobject; var key: Char ); begin if not charinset (Key, ['1 '.. '5']) then key: = #0; end; Procedure tform1.formcreate (Sender: tobject); begin edit1.text: = '1'; end; Procedure tform1.formdestroy (Sender: tobject ); begin if assigned (mysemaphore) Then mysemaphore. free; end.