日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多线程编程(4) - 多线程同步之 Mutex (互斥对象)

發布時間:2023/12/19 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程编程(4) - 多线程同步之 Mutex (互斥对象) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

原理分析:
互斥對象是系統內核對象, 各線程都可以擁有它, 誰擁有誰就能執行;
執行完畢, 用 ReleaseMutex 函數釋放擁有權, 以讓其他等待的線程使用.
其他線程可用 WaitForSingleObject 函數排隊等候(等候也可以理解為排隊申請).

使用過程:

var hMutex: THandle; {應該先聲明一個全局的互斥句柄} CreateMutex {建立一個互斥對象} WaitForSingleObject {用等待函數排隊等候} ReleaseMutex {釋放擁有權} CloseHandle {最后釋放互斥對象}


ReleaseMutex、CloseHandle 的參數都是 CreateMutex 返回的句柄, 關鍵是 CreateMutex 函數:

function CreateMutex(lpMutexAttributes: PSecurityAttributes;bInitialOwner: BOOL; {是否讓創建者(此例中是主線程)擁有該互斥對象}lpName: PWideChar {可以給此互斥對象取個名字, 如果不要名字可賦值為 nil} ): THandle; { 1、第一個參數前面說過. 2、第二個參數在這里一定要是 False, 如果讓主線程擁有互斥, 從理論上講, 得等程序退出后其他線程才有機會;取值 False 時, 第一個執行的線程將會最先擁有互斥對象, 一旦擁有其他線程就得先等等. 3、第三個參數, 如果給個名字, 函數將從系統中尋找是否有重名的互斥對象, 如果有則返回同名對象的存在的句柄;如果賦值為 nil 將直接創建一個新的互斥對象; 下個例子將會有名字. } varf: Integer; {用這個變量協調一下各線程輸出的位置}hMutex: THandle; {互斥對象的句柄}function MyThreadFun(p: Pointer): DWORD; stdcall; vari,y: Integer; beginInc(f);y := 20 * f;for i := 0 to 50000 dobeginif WaitForSingleObject(hMutex, INFINITE) = WAIT_OBJECT_0 thenbeginForm1.Canvas.Lock;Form1.Canvas.TextOut(20, y, IntToStr(i));Form1.Canvas.Unlock;Sleep(0); {稍稍耽擱一點, 不然有時 Canvas 會協調不過來}ReleaseMutex(hMutex);end;end;Result := 0; end;procedure TForm1.Button1Click(Sender: TObject); varThreadID: DWORD; beginRepaint;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); beginhMutex := CreateMutex(nil, False, nil); end;procedure TForm1.FormDestroy(Sender: TObject); beginCloseHandle(hMutex); end; Mutex 作為系統核心對象是可以跨進程的(臨界區就不行), 我們可以利用互斥對象禁止程序重復啟動.

工作思路:
先用 OpenMutex 嘗試打開一個自定義名稱的 Mutex 對象, 如果打開失敗說明之前沒有這個對象存在;
如果之前沒有這個對象, 馬上用 CreateMutex 建立一個, 此時的程序應該是第一次啟動;
再重復啟動時, 那個 OpenMutex 就有結果了, 然后強制退出.
最后在程序結束時用 CloseHandle 釋放 Mutex 對象.

function OpenMutex(dwDesiredAccess: DWORD; {打開權限}bInheritHandle: BOOL; {能否被當前程序創建的進程繼承}pName: PWideChar {Mutex 對象的名稱} ): THandle; stdcall; {成功返回 Mutex 的句柄; 失敗返回 0}
注意, 這里的 CreateMutex 函數應該有個名了, 因為 OpenMutex 要用到;
另外, CreateMutex 的第二個參數已經不重要了(也就是 True 和 False 都行), 因為這里是用其名稱來判斷的.

程序可以這樣寫:
unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs;typeTForm1 = class(TForm)procedure FormCreate(Sender: TObject);procedure FormDestroy(Sender: TObject);end;varForm1: TForm1;implementation{$R *.dfm}varhMutex: THandle; constNameMutex = 'MyMutex';procedure TForm1.FormCreate(Sender: TObject); beginif OpenMutex(MUTEX_ALL_ACCESS, False, NameMutex) <> 0 thenbeginShowMessage('該程序已啟動');Application.Terminate;end;hMutex := CreateMutex(nil, False, NameMutex); end;procedure TForm1.FormDestroy(Sender: TObject); beginCloseHandle(hMutex); end;end.
這一般都是寫在 dpr 主程序里, 省得讓后啟動的程序執行些無用的代碼:
program Project1;usesForms, Windows,Unit1 in 'Unit1.pas' {Form1};{$R *.res}varhMutex: THandle; constNameMutex = 'MyMutex';begin{主線程入口}if OpenMutex(MUTEX_ALL_ACCESS, False, NameMutex) <> 0 thenbeginMessageBox(0, '該程序已啟動', '提示', MB_OK);Application.Terminate;end;hMutex := CreateMutex(nil, False, NameMutex);Application.Initialize;Application.MainFormOnTaskbar := True;Application.CreateForm(TForm1, Form1);Application.Run;CloseHandle(hMutex);{主線程出口} end.

轉載于:https://www.cnblogs.com/hnxxcxg/archive/2010/04/21/2940722.html

總結

以上是生活随笔為你收集整理的多线程编程(4) - 多线程同步之 Mutex (互斥对象)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。