Principle Analysis:
A mutex is a system kernel object that can be owned by each thread and executed by anyone;
After the execution is complete, use the releasemutex function to release the ownership so that other waiting threads can use it.
Other threads can wait in queue using the waitforsingleobject function (waiting can also be understood as queuing application ).
Usage process:
VaR hmutex: thandle; {A Global mutex handle should be declared first} createmutex {create a mutex object} waitforsingleobject {Wait in queue with function} releasemutex {release ownership} closehandle {last release mutex object}
The releasemutex and closehandle parameters are all the handles returned by createmutex. The key is the createmutex function:
Function createmutex (lpmutexattributes: psecurityattributes; binitialowner: bool; {whether to allow the creator (in this example, the main thread) to own the mutex object} lpname: pwidechar {you can give this mutex object a name, if no name can be assigned to nil}): thandle; {1. The first parameter was previously mentioned. 2. The second parameter must be false here. If the main thread is mutually exclusive, theoretically, it must beProgramOther threads have the opportunity to exit. When the value is false, the first thread for execution will first have mutex objects. Once other threads have the mutex object, they must wait. 3. For the third parameter, if a name is given, the function will look for mutex objects with duplicate names from the system. If yes, a handle with the same name will be returned; if the value is nil, a new mutex object will be created directly. In the next example, a name will be created .}
In this example:
Code File:
Unit unit1; interfaceuses windows, messages, extensions, variants, classes, graphics, controls, forms, dialogs, stdctrls; Type tform1 = Class (tform) button1: tbutton; Procedure button1click (Sender: tobject); Procedure formcreate (Sender: tobject); Procedure formdestroy (Sender: tobject); end; var form1: tform1; implementation {$ R *. DFM} var F: integer; {coordinate the output location of each thread with this variable} hmutex: thandle; {handle to mutex object} function mythreadfun (P: pointer): DWORD; stdcall; var I, Y: integer; begin Inc (f); y: = 20 * F; for I: = 0 to 50000 do begin if waitforsingleobject (hmutex, infinite) = wait_object_0 then begin form1.canvas. lock; form1.canvas. textout (20, Y, inttostr (I); form1.canvas. unlock; sleep (0); {slightly delayed, or sometimes canvas won't be able to coordinate} releasemutex (hmutex); end; Result: = 0; end; procedure tform1.button1click (Sender: tobject); var threadid: DWORD; begin 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; Procedure tform1.formcreate (Sender: tobject); begin hmutex: = createmutex (nil, false, nil); end; Procedure tform1.formdestroy (Sender: tobject); begin closehandle (hmutex); 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 endend
The syncobjs unit has encapsulated tmutex classes. It seems that the API is not as fast as it is, and the internal mechanism is slightly different, but the usage is similar:
Unit unit1; interfaceuses windows, messages, extensions, variants, classes, graphics, controls, forms, dialogs, stdctrls; Type tform1 = Class (tform) button1: tbutton; Procedure button1click (Sender: tobject); Procedure formcreate (Sender: tobject); Procedure formdestroy (Sender: tobject); end; var form1: tform1; implementation {$ R *. DFM} uses syncobjs; var F: integer; mymutex: tmutex; function mythreadfun (P: pointer): DWORD; stdcall; var I, Y: integer; begin Inc (f ); y: = 20 * F; for I: = 0 to 50000 do begin if mymutex. waitfor (infinite) = wrsignaled then begin form1.canvas. lock; form1.canvas. textout (20, Y, inttostr (I); form1.canvas. unlock; mymutex. release; end; Result: = 0; end; Procedure tform1.button1click (Sender: tobject); var threadid: DWORD; begin 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; procedure tform1.formcreate (Sender: tobject); begin mymutex: = tmutex. create (false); end; Procedure tform1.formdestroy (Sender: tobject); begin mymutex. free; end.