在 Windows 環境下,多執行緒能顯著提升應用程式回應性與資源利用率:
多執行緒共享記憶體空間,同步是指協調執行緒存取共享資料,避免競爭條件。Win32 以時間片輪轉執行緒,無法預測中斷點,因此必須引入同步物件。
經典同步問題包括:生產者-消費者、讀者-寫者、哲學家進餐。本文以生產者-消費者為例實作。
VCL 封裝 Win32 Thread API 為 TThread,簡化開發。主要屬性與方法:
| 屬性/方法 | 用途 |
|---|---|
| Priority | 執行緒優先權 |
| Suspended | 是否暫停 |
| Terminated | 標記請求結束 |
| ThreadID | 系統唯一識別碼 |
| Synchronize(TThreadMethod) | 將呼叫封送至主 VCL 執行緒,安全存取 UI |
| WaitFor() | 阻塞直到執行緒結束 |
| Resume()/Suspend() | 喚醒/暫停(成對使用) |
TCanvas::Lock()/Unlock()。TCriticalSection 全域實例,Acquire()/Release() 互斥進入。TMultiReadExclusiveWriteSynchronizer,適合「頻繁讀、少量寫」場景,BeginRead/EndRead、BeginWrite/EndWrite。Synchronize(),由主執行緒在安全時機執行。WaitFor():等待特定執行緒完全結束。TEvent 全域實例,SetEvent() 發送訊號,ResetEvent() 清除。適用於「等待任務完成」而非「等待執行緒結束」。場景:兩個生產者執行緒、一個消費者執行緒,共享大小為 5 的緩衝區(整數陣列)。使用 TCriticalSection 保護緩衝區索引,兩個 TEvent(BeginProduce、BeginConsume)協調生產/消費節奏。
執行畫面:
void __fastcall TProducerThread::Execute() {
int i = 0, j;
while (i < 100) { // 每個生產者產出 100 個項目
Sleep(1000); // 延遲以利觀察
if (Form1->buffer_size > 0)
Form1->BeginConsume->SetEvent(); // 通知消費者
Form1->ProduceGuard->Acquire(); // 進入臨界區
i++;
Form1->StrResult = IntToStr(i);
j = Form1->buffer_size;
Form1->Product[j] = i;
Form1->buffer_size++;
Synchronize(&ShowResult); // 刷新 UI
Form1->BeginConsume->SetEvent();
if (Form1->buffer_size == 5) // 緩衝區滿,等待消費者騰空
Form1->BeginProduce->WaitFor(INFINITE);
Sleep(1000);
Form1->ProduceGuard->Release(); // 離開臨界區
}
// 收尾:喚醒消費者處理剩餘項目
while (Form1->buffer_size > 0)
Form1->BeginConsume->SetEvent();
}
void __fastcall TConsumerThread::Execute() {
for (int i = 0; i < 200; i++) { // 總共消費 200 個(兩生產者各 100)
Sleep(100);
Form1->BeginConsume->WaitFor(INFINITE); // 等待生產者通知
int j = Form1->buffer_size - 1;
Form1->StrResult = IntToStr(Form1->Product[j]);
Form1->buffer_size--;
Synchronize(&ShowResult); // 刷新 UI
if (Form1->buffer_size == 4) // 緩衝區不再滿,喚醒生產者
Form1->BeginProduce->SetEvent();
Sleep(100);
}
}
TCriticalSection ProduceGuard 確保 buffer_size 與 Product[] 讀寫原子性。BeginProduce、BeginConsume 事件分別對應「緩衝區非滿」、「緩衝區非空」條件。Synchronize() 封送至主執行緒。多執行緒程式設計的核心在於識別共享資源、選擇適當同步原語、設計無死結的協議。C++Builder 的 TThread、TCriticalSection、TEvent 提供了完整的工具箱,配合 Synchronize() 機制,讓開發者能專注於業務邏輯而非底層 API 細節。生產者-消費者模式更是高併發系統(訊息佇列、任務調度、資料管線)的基石,掌握其實作細節將受益無窮。