首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 多執行緒實現執行緒間通訊與同步完整實戰

     編輯:VC 教學

核心概念速覽

  • 進程:獨立虛擬位址空間、代碼、資料、資源;
  • 執行緒:進程內獨立執行流,共享進程資源(全域變數、Handle),擁有私有堆疊、CPU 時間片;
  • 分類:UI 執行緒(含訊息迴圈,如主執行緒)vs 工作執行緒(無訊息迴圈,後台計算/IO)。

執行緒建立與控制

工作執行緒(最常用)

// 1. 執行緒函數
UINT __cdecl WorkerThread(LPVOID pParam) {
    CMyData* pData = (CMyData*)pParam;
    while (!pData->bStop) {
        // 執行任務...
        Sleep(100);
    }
    return 0;
}

// 2. 啟動
CWinThread* pThread = AfxBeginThread(WorkerThread, pData, THREAD_PRIORITY_NORMAL);

UI 執行緒

// 需從 CWinThread 衍生,使用 DECLARE_DYNCREATE/IMPLEMENT_DYNCREATE
class CMyUIThread : public CWinThread {
    DECLARE_DYNCREATE(CMyUIThread)
    virtual BOOL InitInstance() { /* 建視窗 */ return TRUE; }
};
IMPLEMENT_DYNCREATE(CMyUIThread, CWinThread)

// 啟動
AfxBeginThread(RUNTIME_CLASS(CMyUIThread), THREAD_PRIORITY_NORMAL);

同步機制工具箱

機制適用場景關鍵 API
Critical Section進程內高頻短暫互斥CCriticalSection::Lock/Unlock
Mutex跨進程互斥CMutex, WaitForSingleObject
Event執行緒間信號通知CEvent::SetEvent/ResetEvent
Semaphore資源計數控制CSemaphore

實戰案例:生產者-消費者數字排序

共享資料結構

struct SharedData {
    CCriticalSection cs;
    CEvent evDataReady;
    CEvent evSpaceReady;
    int buffer[100];
    int head = 0, tail = 0, count = 0;
    BOOL bStop = FALSE;
} g_Data;

生產者執行緒

UINT Producer(LPVOID) {
    for (int i = 0; i < 1000 && !g_Data.bStop; ++i) {
        g_Data.evSpaceReady.Lock(); // 等待空位
        g_Data.cs.Lock();
        g_Data.buffer[g_Data.tail] = rand() % 1000;
        g_Data.tail = (g_Data.tail + 1) % 100;
        g_Data.count++;
        g_Data.cs.Unlock();
        g_Data.evDataReady.SetEvent(); // 通知有數據
    }
    return 0;
}

消費者執行緒(排序輸出)

UINT Consumer(LPVOID) {
    std::vector vec;
    while (!g_Data.bStop || g_Data.count > 0) {
        g_Data.evDataReady.Lock();
        g_Data.cs.Lock();
        if (g_Data.count > 0) {
            vec.push_back(g_Data.buffer[g_Data.head]);
            g_Data.head = (g_Data.head + 1) % 100;
            g_Data.count--;
        }
        g_Data.cs.Unlock();
        g_Data.evSpaceReady.SetEvent();

        if (vec.size() >= 100) {
            std::sort(vec.begin(), vec.end());
            // 輸出或傳遞給 UI...
            vec.clear();
        }
    }
    return 0;
}

啟動與清理

CWinThread* pProd = AfxBeginThread(Producer, NULL);
CWinThread* pCons = AfxBeginThread(Consumer, NULL);

// 程式結束前
g_Data.bStop = TRUE;
g_Data.evDataReady.SetEvent();
g_Data.evSpaceReady.SetEvent();
WaitForSingleObject(pProd->m_hThread, INFINITE);
WaitForSingleObject(pCons->m_hThread, INFINITE);

優先級與調度

  • GetThreadPriority() / SetThreadPriority():相對優先級(同優先權層級內);
  • GetPriorityClass() / SetPriorityClass():進程優先權層級(跨層級);
  • 高優先級搶佔低優先級,同級時間片輪轉。

執行緒終止三種方式

  1. 函數自然返回(推薦,配合旗標 bStop);
  2. AfxEndThread() 內部自殺;
  3. TerminateThread() 強制殺掉(危險:資源洩漏、鎖未釋放),慎用。

避坑指南

  • UI 操作只能在 UI 執行緒(主執行緒)進行,工作執行緒需 PostMessage 轉發;
  • 共享資料必須加鎖,volatile 不能替代鎖;
  • 避免巢狀鎖導致死鎖,固定鎖順序;
  • 執行緒函數參數生命週期必須覆蓋執行緒存活期;
  • MFC 物件跨執行緒傳遞需小心(CWnd* 等不可直接跨執行緒用)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved