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

VC++ 實作生產者-消費者模式:多執行緒同步完整範例

     編輯:VC++

前言

多執行緒協作處理共享資源是常見需求。本文示範使用 MFC 同步物件 CSemaphore、CMutex 實作經典的生產者-消費者模式。

問題描述

  • 生產者持續將資料放入共享緩衝區
  • 消費者持續從緩衝區取出資料
  • 緩衝區滿時生產者等待;空時消費者等待
  • 避免資料覆寫與重複消費

同步機制設計

完整實作程式碼

1. 對話方塊類別成員變數

class CProdConsDlg : public CDialog
{
    bool m_bSlowDisplay;              // 是否緩慢顯示
    CWinThread* m_pProducerThread;    // 生產者執行緒
    CWinThread* m_pConsumerThread;    // 消費者執行緒
    CSemaphore* m_pSemEmpty;          // 空信號
    CSemaphore* m_pSemFull;           // 滿信號
    CMutex* m_pMutex;                 // 互斥鎖
    CString m_strProducerBuf;         // 生產資料顯示
    CString m_strConsumerBuf;         // 消費資料顯示
    // ...
};

2. 生產者執行緒類別

class CProducerThread : public CWinThread
{
    CProdConsDlg* m_pDlg;
public:
    CProducerThread(CProdConsDlg* pDlg) : m_pDlg(pDlg) {}
    
    virtual int Run()
    {
        CSingleLock lock(m_pDlg->m_pMutex);
        for (int i = 0; i < MAX_DATA_COUNT; i++)
        {
            m_pDlg->m_pSemEmpty->Lock();           // 等待空槽
            lock.Lock();
            m_pDlg->m_strProducerBuf.Format(_T("%0.10d"), i);
            lock.Unlock();
            m_pDlg->m_pSemFull->Unlock();          // 通知有資料
            if (m_pDlg->m_bSlowDisplay) Sleep(50);
        }
        return CWinThread::Run();
    }
};

3. 消費者執行緒類別

class CConsumerThread : public CWinThread
{
    CProdConsDlg* m_pDlg;
    char m_data[CONSUMER_BUF_SIZE];
public:
    CConsumerThread(CProdConsDlg* pDlg) : m_pDlg(pDlg) {}
    
    virtual int Run()
    {
        char* pBuf = m_data;
        for (int i = 0; i < MAX_DATA_COUNT; i += 10)
        {
            m_pDlg->m_pSemFull->Lock();            // 等待資料
            m_pDlg->m_pMutex->Lock();
            sprintf(pBuf, "%s", m_pDlg->m_strProducerBuf);
            BOOL bSlow = m_pDlg->m_bSlowDisplay;
            m_pDlg->m_pMutex->Unlock();
            
            pBuf += 10;
            if (pBuf >= m_data + CONSUMER_BUF_SIZE - 10) pBuf = m_data;
            m_data[CONSUMER_BUF_SIZE] = 0;
            
            m_pDlg->m_pMutex->Lock();
            m_pDlg->m_strConsumerBuf = m_data;
            m_pDlg->m_pMutex->Unlock();
            
            if (bSlow) Sleep(100);
            m_pDlg->m_pSemEmpty->Unlock();         // 釋放空槽
        }
        return CWinThread::Run();
    }
};

4. 啟動執行緒(在對話方塊按鈕或 OnInitDialog 中)

m_pSemFull = new CSemaphore(0, 1);      // 初始 0,最大 1
m_pSemEmpty = new CSemaphore(1, 1);     // 初始 1,最大 1
m_pMutex = new CMutex();

m_pProducerThread = new CProducerThread(this);
m_pConsumerThread = new CConsumerThread(this);

m_strProducerBuf = _T("1234567890");
UpdateData(FALSE);

m_pProducerThread->CreateThread(CREATE_SUSPENDED);
m_pProducerThread->SetThreadPriority(THREAD_PRIORITY_IDLE);
m_pConsumerThread->CreateThread(CREATE_SUSPENDED);
m_pConsumerThread->SetThreadPriority(THREAD_PRIORITY_IDLE);

m_pProducerThread->ResumeThread();
m_pConsumerThread->ResumeThread();

關鍵點總結

  • 兩個 Semaphore 分別追蹤「空槽」與「資料項」數量
  • Mutex 保護實際緩衝區記憶體存取
  • Lock/Unlock 配對確保同步正確性
  • 執行緒優先權設為 IDLE 避免佔用過多 CPU
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
物件用途初始值/最大值
CSemaphore m_semEmpty空槽位計數初始 = 緩衝區大小,最大 = 緩衝區大小
CSemaphore m_semFull資料項計數初始 = 0,最大 = 緩衝區大小
CMutex m_mutex保護緩衝區存取—