Mutex(Mutual Exclusion Object,互斥對象)是 Windows 核心提供的一種同步原語,屬於核心對象。它的核心特性是同一時間只允許一個線程擁有它。擁有 Mutex 的線程可以進入受保護的程式碼區段(Critical Section),其他試圖獲取同一 Mutex 的線程將被迫排隊等待,直到擁有者釋放它為止。
function CreateMutex(
lpMutexAttributes: PSecurityAttributes; // 安全屬性,通常為 nil
bInitialOwner: BOOL; // 建立者是否立即擁有,多線程下建議 False
lpName: PWideChar // 物件名稱,nil 為無名;同名則跨進程共享
): THandle; stdcall;
下列程式碼示範如何使用 Mutex 保護 Canvas 繪圖操作,確保多線程不會同時存取 Canvas 導致畫面錯亂。
unit Unit1;
interface
uses Windows, Messages, SysUtils, 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; // 協調各線程輸出垂直位置
hMutex: THandle; // 全域 Mutex 句柄
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); // 讓出時間片,緩解 Canvas 壓力
ReleaseMutex(hMutex);
end;
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
// 建立無名 Mutex,初始擁有者為 False
hMutex := CreateMutex(nil, False, nil);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
CloseHandle(hMutex);
end;
end.
Delphi 的 SyncObjs 單元提供 TMutex 類,用法更符合物件導向風格,內部同樣呼叫核心 API,效能略低但碼碼更清晰:
uses SyncObjs;
var MyMutex: TMutex;
// 建立
MyMutex := TMutex.Create(False);
// 等待
if MyMutex.WaitFor(INFINITE) = wrSignaled then
begin
// 受保護區域
MyMutex.Release;
end;
// 釋放
MyMutex.Free;

五條線程依序在各自行輸出 0~50000,畫面整齊無重疊,證明 Mutex 成功序列化了 Canvas 存取。