Delphi多線程學習(5):互斥量Mutex


      互斥量是系統內核對象,誰擁有就誰執行。它與臨界區工作很類似。不同處在於:1、互斥量可以跨進程邊界同步線程。2、可以給互斥量取個名字,通過引用互斥量的名字來使用一個已知的互斥量對象。

     使用互斥量之類的對象需要反復調用系統內核,期間需要進行進程上下文轉換和控制級別轉換,大概需要耗費400到600個時間周期。

      又是圖書館的比喻,現在是搞一個鎖,把鑰匙(互斥量句柄)交給管理員(操作系統),每一個人(線程)想要借書的時候,都要向管理員拿鑰匙。當有人在使用的時候,另一人必須等待,等到鑰匙有空的時候(互斥量進入信號狀態),才能拿到鑰匙(擁有了句柄)辦理借書業務(此時互斥量進入非信號狀態直到辦完業務)。

   使用互斥量的步驟:

1、聲明一個全局的互斥量句柄變量(var hMutex: THandle;);

2、創建互斥量:CreateMutex(
                          lpMutexAttributes: PSecurityAttributes;
                          bInitialOwner: BOOL; 
                          lpName: PWideChar   ): THandle;

  (lpMutexAttributes參數:指向TSecurityAttributes的指針,安全屬性,一般用缺省安全屬性nil;

    bInitialOwer參數:表示創建的互斥量線程是否是互斥量的屬主,如果該參數為False互斥量就沒屬主,一般來講應設為False,否則如果設為True的話,要當主線程結束其他線程才成為它的屬主才能運行;

   lpName參數:是互斥量的名字,若打算取名的話,則傳入nil。)

3、用等待函數控制線程進入同步代碼塊:WaitForSingleObject(
                                                            hHandle:THandel;
                                                           dwMilliseconds:DWORD):DWORD;

(hHandel參數:是對象的句柄,不同對象信號狀態不同,對於互斥量而言當沒有線程占有時,互斥量就時入信號狀態;

   dwMilliseconds參數:可以是一個時間段,可以是0表示僅檢查對象狀態后立即返回,可以是INFINITE值表示函數一直等待直到對象進入信號狀態;

返回值常量如下:WAIT_ABANDONED指定的對象是互斥量對象,擁有這個互斥量對象的線程在沒有釋放互斥量之前就已經終止,稱作廢棄互斥量,此時該互斥量歸調用線程所擁有,並把這個互斥量設為非信號狀態;WAIT_OBJECT_0指定對象的進入信號狀態;WAIT_TIMEOUT等待時間已過,對象狀態依然是無信號狀態)

4、執行線程運行代碼。

5、線程運行完后釋放互斥量的擁有權:ReleaseMutex(hMutex: THandle);

6、最后關閉互斥量:CloseHandle(hMutex: THandle);

同樣的例子,使用互斥量:

     unit Unit2;  
  1.    
  2. interface  
  3.    
  4. uses  
  5.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  6.   Dialogs, StdCtrls;  
  7.    
  8. type  
  9.   TForm2 = class(TForm)  
  10.     ListBox1: TListBox;  
  11.     Button1: TButton;  
  12.     procedure Button1Click(Sender: TObject);  
  13.     procedure FormCreate(Sender: TObject);  
  14.     procedure FormDestroy(Sender: TObject);  
  15.   private  
  16.     { Private declarations }  
  17.   public  
  18.     { Public declarations }  
  19.   end;  
  20.    
  21. var  
  22.   Form2: TForm2;  
  23.   hMutex:THandle;  
  24. implementation  
  25.    
  26. uses MyThread;  
  27.    
  28. {$R *.dfm}  
  29.    
  30. procedure TForm2.Button1Click(Sender: TObject);  
  31. begin  
  32.   TMyThread.Create(False);  
  33.   TMyThread.Create(False);  
  34.   TMyThread.Create(False);       
  35. end;  
  36.    
  37. procedure TForm2.FormCreate(Sender: TObject);  
  38. begin  
  39.   hMutex:=CreateMutex(nil,false,'MyThreadDemo');  
  40. end;  
  41.    
  42. procedure TForm2.FormDestroy(Sender: TObject);  
  43. begin  
  44.   CloseHandle(hMutex);  
  45. end;  
  46.    
  47. end.unit MyThread;  
  48.    
  49. interface  
  50.    
  51. uses  
  52.   Classes,StdCtrls,SysUtils,Windows;  
  53.    
  54. type  
  55.   TMyThread = class(TThread)  
  56.   private  
  57.     { Private declarations }  
  58.     str:String;  
  59.     procedure AddList;  
  60.   protected  
  61.     procedure Execute; override;  
  62.   end;  
  63.    
  64. implementation  
  65.    
  66. uses Unit2;  
  67.    
  68. { TMyThread }  
  69.    
  70. procedure TMyThread.AddList;  
  71. begin  
  72.   Form2.ListBox1.Items.Add(str);  
  73. end;  
  74.    
  75. procedure TMyThread.Execute;  
  76. var  
  77.   i:Integer;  
  78. begin  
  79.   { Place thread code here }  
  80.   FreeOnTerminate:=True;  
  81.   if WaitForSingleObject(hMutex,INFINITE)=WAIT_OBJECT_0 then  
  82.   begin  
  83.    try  
  84.     for i := 0 to 99 do  
  85.       begin  
  86.         if not Terminated then  
  87.           begin  
  88.             str:=Format('線程ID:%.4d,第%.2d個循環。',[GetCurrentThreadId,i]);  
  89.             Synchronize(AddList);  
  90.           end;  
  91.       end;  
  92.    finally  
  93.     ReleaseMutex(hMutex);  
  94.    end;  
  95.   end;  
  96. end;  
  97.    
  98. end

 

運行結果與前文相似,這里借用前文的圖(除了線程ID不同)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM