Windows 生产者-消费者

生产者-消费者模型是学习线程同步的经典模型,网上有关Windows版本的文章也有很多,但是你能找到的90%的都是有问题的

大部分都能很好的处理共享数据队列互斥访问,但是在判断队列空或者满的时候没有做任何线程保护,也就是说那样的示例是

没法用在实际商业项目中的,下面的例子用使用互斥量(Mutex)和信号量(Semaphore)来出实现生产者-消费者,互斥量用来

同步生产者和消费者线程同步访问数据队列的问题,信号量用来处理队列中资源个数的问题

首先创建1个互斥量

hMutex = CreateMutex(NULL, false, NULL);

创建2个信号量,一个用来表示队列剩余空间,一个表示队列中可用数据的个数,这里假定队列的容量是10

hProduceSemp = CreateSemaphore(NULL, 10, 10, NULL);
hConsumeSemp = CreateSemaphore(NULL, 0, 10, NULL);

其中hProduceSemp表示队列最大长度是10,当前可用10

hConsumeSemp表示对垒最大长度是10,当前可用是0(初始时刻我们还没有给队列中生产任何数据,可用数据当然就是0喽)

创建一个辅助的Struct用来从外部传入参数给线程处理函数

typedef struct ThreadData
{
    CProductAndConsumer* pThis;
    int ThreadIndex;
}ThreadData;

创建生产者和消费者处理线程

for (size_t i = 0; i < 2; i++)
{
    ThreadData* pData = new ThreadData();
    pData->pThis = this;
    pData->ThreadIndex = i + 1;
    CreateThread(NULL, 0, ProduceProc, (LPVOID)pData, 0, NULL);
}

for (size_t i = 0; i < 4; i++)
{
    ThreadData* pData = new ThreadData();
    pData->pThis = this;
    pData->ThreadIndex = i + 1;
    CreateThread(NULL, 0, ConsumeProc, (LPVOID)pData, 0, NULL);
}

实现生产者线程处理函数ProduceProc,和具体的生产过程

DWORD WINAPI CProductAndConsumer::ProduceProc(__in  LPVOID lpParameter)
{
    CTools::OutputDebugPrintf("ProduceProc enter\n");
    ThreadData* pData = (ThreadData*)lpParameter;
    CProductAndConsumer* pThis = pData->pThis;
    while (!pThis->isQuit())
    {
        WaitForSingleObject(pThis->hProduceSemp, INFINITE);
        pThis->Produce(pData->ThreadIndex);
        ReleaseSemaphore(pThis->hConsumeSemp, 1, NULL);
        Sleep(rand() % 900 + 100);
    }
    return 0;
}
// 生产
int CProductAndConsumer::Produce(int nThreadIndex)
{
    WaitForSingleObject(hMutex, INFINITE);
    srand(mProduceResIndex);
    int nRandValue =rand() % 999 + 1000;
    mRes[mProduceResIndex %10] = nRandValue;
    CTools::OutputDebugPrintf("ProduceThread-%d count:%d Value:%d\n", nThreadIndex, mProduceResIndex, nRandValue);
    mProduceResIndex++;
    ReleaseMutex(hMutex);
    return 0;
}

实现消费者处理函数和具体消费过程

DWORD WINAPI CProductAndConsumer::ConsumeProc(__in  LPVOID lpParameter)
{
    CTools::OutputDebugPrintf("ConsumeProc enter\n");
    ThreadData* pData = (ThreadData*)lpParameter;
    CProductAndConsumer* pThis = pData->pThis;
    while (!pThis->isQuit())
    {
        WaitForSingleObject(pThis->hConsumeSemp, INFINITE);
        pThis->Consume(pData->ThreadIndex);
        ReleaseSemaphore(pThis->hProduceSemp, 1, NULL);
        Sleep(rand()%900+100);
    }
    return 0;
}
// 消费
int CProductAndConsumer::Consume(int nThreadIndex)
{
    WaitForSingleObject(hMutex, INFINITE);
    CTools::OutputDebugPrintf("ConsumeThread-%d count:%d Value:%d\n", nThreadIndex, mConsumeResIndex, mRes[mConsumeResIndex%10]);
    mConsumeResIndex++;
    ReleaseMutex(hMutex);
    return 0;
}

代码比较简单,看看就能懂

全部代码

头文件

class CProductAndConsumer
{
public:
    CProductAndConsumer();
    ~CProductAndConsumer();


    int Init();

private:
    int Produce(int nThreadIndex);
    int Consume(int nThreadIndex);

    static DWORD WINAPI ProduceProc(__in  LPVOID lpParameter);
    static DWORD WINAPI ConsumeProc(__in  LPVOID lpParameter);
    bool isQuit();
private:
    HANDLE hProduceSemp;
    HANDLE hConsumeSemp;
    HANDLE hMutex;
    int mRes[10];
    int mProduceResIndex;
    int mConsumeResIndex;
};

实现文件

#include "CProductAndConsumer.h"
#include "CTools.h"

typedef struct ThreadData
{
    CProductAndConsumer* pThis;
    int ThreadIndex;
}ThreadData;

CProductAndConsumer::CProductAndConsumer()
{
    mProduceResIndex = 0;
    mConsumeResIndex = 0;
}


CProductAndConsumer::~CProductAndConsumer()
{
}

int CProductAndConsumer::Init()
{
    hProduceSemp = CreateSemaphore(NULL, 10, 10, NULL);
    hConsumeSemp = CreateSemaphore(NULL, 0, 10, NULL);
    hMutex = CreateMutex(NULL, false, NULL);

    for (size_t i = 0; i < 2; i++)
    {
        ThreadData* pData = new ThreadData();
        pData->pThis = this;
        pData->ThreadIndex = i + 1;
        CreateThread(NULL, 0, ProduceProc, (LPVOID)pData, 0, NULL);
    }

    for (size_t i = 0; i < 4; i++)
    {
        ThreadData* pData = new ThreadData();
        pData->pThis = this;
        pData->ThreadIndex = i + 1;
        CreateThread(NULL, 0, ConsumeProc, (LPVOID)pData, 0, NULL);
    }
    return 0;
}

DWORD WINAPI CProductAndConsumer::ProduceProc(__in  LPVOID lpParameter)
{
    CTools::OutputDebugPrintf("ProduceProc enter\n");
    ThreadData* pData = (ThreadData*)lpParameter;
    CProductAndConsumer* pThis = pData->pThis;
    while (!pThis->isQuit())
    {
        WaitForSingleObject(pThis->hProduceSemp, INFINITE);
        pThis->Produce(pData->ThreadIndex);
        ReleaseSemaphore(pThis->hConsumeSemp, 1, NULL);
        Sleep(rand() % 900 + 100);
    }
    return 0;
}


DWORD WINAPI CProductAndConsumer::ConsumeProc(__in  LPVOID lpParameter)
{
    CTools::OutputDebugPrintf("ConsumeProc enter\n");
    ThreadData* pData = (ThreadData*)lpParameter;
    CProductAndConsumer* pThis = pData->pThis;
    while (!pThis->isQuit())
    {
        WaitForSingleObject(pThis->hConsumeSemp, INFINITE);
        pThis->Consume(pData->ThreadIndex);
        ReleaseSemaphore(pThis->hProduceSemp, 1, NULL);
        Sleep(rand()%900+100);
    }
    return 0;
}

bool CProductAndConsumer::isQuit()
{
    return false;
}

// 生产
int CProductAndConsumer::Produce(int nThreadIndex)
{
    WaitForSingleObject(hMutex, INFINITE);
    srand(mProduceResIndex);
    int nRandValue =rand() % 999 + 1000;
    mRes[mProduceResIndex %10] = nRandValue;
    CTools::OutputDebugPrintf("ProduceThread-%d count:%d Value:%d\n", nThreadIndex, mProduceResIndex, nRandValue);
    mProduceResIndex++;
    ReleaseMutex(hMutex);
    return 0;
}
// 消费
int CProductAndConsumer::Consume(int nThreadIndex)
{
    WaitForSingleObject(hMutex, INFINITE);
    CTools::OutputDebugPrintf("ConsumeThread-%d count:%d Value:%d\n", nThreadIndex, mConsumeResIndex, mRes[mConsumeResIndex%10]);
    mConsumeResIndex++;
    ReleaseMutex(hMutex);
    return 0;
}

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值