• 操作系统 生产者消费者 练习


    习题:假设

    有10个生产者和10个消费者 

    初始物品100个

    生产者一次生产一件物品  消费者一次消费一件物品

    生产者每生产一件物品  消费者就消费掉一件  

    消费者每消费掉一件  生产者就生产一件物品 

    直到这样交互100次

    思想 :10个消费者为一个线程池  10个生产者为一个线程池

    消费者任务  物品--;

    生产者任务  物品++;

    这里有个条件

    1.

    每次执行 物品--; 或 物品++;时  我们只想让一个生产者或消费者去执行  其他的人等待  所以这里我们用到了互斥量  同一时刻只允许一个线程执行  

    2.

    生产者一次生产一件物品  消费者一次消费一件物品

    生产者每生产一件物品  消费者就消费掉一件  

    这我们可以利用互斥量的信号的获取和释放来实现

    当生产者获取到生产者的互斥量信号  它生产一件物品  然后释放掉消费者的互斥量信号  

    消费者获取到消费者的互斥量信号  它消费一件物品  然后释放掉生产者的互斥量信号 

    如此往复

    完整代码如下

    生产者消费者类的声明

    1. #ifndef CREATER_H
    2. #define CREATER_H
    3. #include
    4. #include
    5. #include
    6. class CreaterConsumer
    7. {
    8. private:
    9. //生产者句柄
    10. HANDLE m_Create;
    11. //消费者句柄
    12. HANDLE m_Consumer;
    13. //生产者线程链表
    14. std::list m_myCreaterlist;
    15. //消费者线程链表
    16. std::list m_myConsumerlist;
    17. //产品数量
    18. long product;
    19. //生产者互斥量
    20. HANDLE m_MutexCreater;
    21. //消费者互斥量
    22. HANDLE m_MutexConsumer;
    23. public:
    24. //记录交互次数
    25. long nCount;
    26. public:
    27. CreaterConsumer();
    28. ~CreaterConsumer();
    29. //创建生产者线程池
    30. bool CreateThreadPool();
    31. //创建消费者线程池
    32. bool ConsumerThreadPool();
    33. //销毁生产者线程池
    34. void DeleteCreaterThreadPool();
    35. //销毁消费者线程池
    36. void DeleteConsumerThreadPool();
    37. //生产者线程函数
    38. static DWORD WINAPI CreateThreadProc(LPVOID lpvoid);
    39. //消费者线程函数
    40. static DWORD WINAPI ConsumerThreadProc(LPVOID lpvoid);
    41. };
    42. #endif // CREATER_H

    生产者消费者类的的定义

    1. #include "creater.h"
    2. #include
    3. using namespace std;
    4. CreaterConsumer::CreaterConsumer()
    5. {
    6. m_Create=NULL;
    7. m_Consumer=NULL;
    8. product=100;
    9. m_MutexCreater=CreateMutex(0,0,0);
    10. m_MutexConsumer=CreateMutex(0,1,0);//开始先让消费者启动交互
    11. nCount=0;
    12. }
    13. CreaterConsumer::~CreaterConsumer()
    14. {
    15. }
    16. bool CreaterConsumer::CreateThreadPool()
    17. {
    18. //创建十个线程到生产者线程列表中去
    19. for(int i=0;i<10;i++)
    20. {
    21. m_Create=CreateThread(0,0,&CreateThreadProc,this,0,0);
    22. if(m_Create)
    23. {
    24. m_myCreaterlist.push_back(m_Create);
    25. }
    26. }
    27. }
    28. bool CreaterConsumer::ConsumerThreadPool()
    29. {
    30. //创建十个线程到消费者线程列表中去
    31. for(int i=0;i<10;i++)
    32. {
    33. m_Consumer=CreateThread(0,0,&CreateThreadProc,this,0,0);
    34. if(m_Consumer)
    35. {
    36. m_myConsumerlist.push_back(m_Consumer);
    37. }
    38. }
    39. }
    40. DWORD WINAPI CreaterConsumer::CreateThreadProc(LPVOID lpvoid)
    41. {
    42. CreaterConsumer* pthis=(CreaterConsumer*)lpvoid;
    43. while(1)
    44. {
    45. //当前交互次数小于100
    46. if(pthis->nCount<100)
    47. {
    48. WaitForSingleObject(pthis->m_MutexCreater,INFINITE);
    49. //当交互次数为 例如:99 时 进来了多个线程
    50. //如果一个交互次数为99 的线程执行完 交互次数变为100 应该不继续执行
    51. //但是剩下的进来的这些线程不会出去 会继续执行 交互次数就会大于100 所以加了一个筛选 if(pthis->nCount>=100)
    52. if(pthis->nCount>=100)
    53. {
    54. //如果此时交互次数>=100 剩下的进来的线程不会继续执行 而是会被筛选出去
    55. ReleaseMutex( pthis->m_MutexConsumer);
    56. continue;
    57. }
    58. //pthis->product++;
    59. //物品数++
    60. InterlockedIncrement(&pthis->product);
    61. //交互次数++
    62. InterlockedIncrement(&pthis->nCount);
    63. //打印交互次数
    64. cout<nCount<
    65. //释放消费者信号
    66. ReleaseMutex(pthis->m_MutexConsumer);
    67. }
    68. }
    69. }
    70. DWORD WINAPI CreaterConsumer::ConsumerThreadProc(LPVOID lpvoid)
    71. {
    72. CreaterConsumer* pthis=(CreaterConsumer*)lpvoid;
    73. while(1)
    74. {
    75. if(pthis->nCount<100)
    76. {
    77. WaitForSingleObject(pthis->m_MutexConsumer,INFINITE);
    78. if(pthis->nCount>=100)
    79. {
    80. ReleaseMutex( pthis->m_MutexCreater);
    81. continue;
    82. }
    83. //pthis->product--;
    84. //物品数--;
    85. InterlockedDecrement(&pthis->product);
    86. //释放生产者信号
    87. ReleaseMutex(pthis->m_MutexCreater);
    88. }
    89. }
    90. }
    91. void CreaterConsumer::DeleteCreaterThreadPool()
    92. {
    93. //遍历生产者列表
    94. auto ite= m_myCreaterlist.begin();
    95. //将生产者列表的每一项都删除
    96. while(ite!=m_myCreaterlist.end())
    97. {
    98. delete *ite;
    99. ite++;
    100. }
    101. //清空列表
    102. m_myCreaterlist.clear();
    103. //释放生产者线程句柄
    104. if(m_Create)
    105. {
    106. CloseHandle(m_Create);
    107. m_Create=NULL;
    108. }
    109. //释放生产者互斥量
    110. if(m_MutexCreater)
    111. {
    112. CloseHandle(m_MutexCreater);
    113. m_MutexCreater=NULL;
    114. }
    115. }
    116. void CreaterConsumer::DeleteConsumerThreadPool()
    117. {
    118. //遍历并删除消费者列表的每一项
    119. auto ite= m_myConsumerlist.begin();
    120. while(ite!=m_myConsumerlist.end())
    121. {
    122. delete *ite;
    123. ite++;
    124. }
    125. //清空消费者列表
    126. m_myConsumerlist.clear();
    127. //释放消费者线程句柄
    128. if(m_Consumer)
    129. {
    130. CloseHandle(m_Consumer);
    131. m_Consumer=NULL;
    132. }
    133. //释放消费者互斥量
    134. if(m_MutexConsumer)
    135. {
    136. CloseHandle(m_MutexConsumer);
    137. m_MutexConsumer=NULL;
    138. }
    139. }

    主函数

    1. #include "creater.h"
    2. #include
    3. using namespace std;
    4. CreaterConsumer::CreaterConsumer()
    5. {
    6. m_Create=NULL;
    7. m_Consumer=NULL;
    8. product=100;
    9. m_MutexCreater=CreateMutex(0,0,0);
    10. m_MutexConsumer=CreateMutex(0,1,0);
    11. nCount=0;
    12. }
    13. CreaterConsumer::~CreaterConsumer()
    14. {
    15. }
    16. bool CreaterConsumer::CreateThreadPool()
    17. {
    18. //创建十个线程到线程列表中去
    19. for(int i=0;i<10;i++)
    20. {
    21. m_Create=CreateThread(0,0,&CreateThreadProc,this,0,0);
    22. if(m_Create)
    23. {
    24. m_myCreaterlist.push_back(m_Create);
    25. }
    26. }
    27. }
    28. bool CreaterConsumer::ConsumerThreadPool()
    29. {
    30. //创建十个线程到线程列表中去
    31. for(int i=0;i<10;i++)
    32. {
    33. m_Consumer=CreateThread(0,0,&CreateThreadProc,this,0,0);
    34. if(m_Consumer)
    35. {
    36. m_myConsumerlist.push_back(m_Consumer);
    37. }
    38. }
    39. }
    40. DWORD WINAPI CreaterConsumer::CreateThreadProc(LPVOID lpvoid)
    41. {
    42. CreaterConsumer* pthis=(CreaterConsumer*)lpvoid;
    43. while(1)
    44. {
    45. if(pthis->nCount<100)
    46. {
    47. WaitForSingleObject(pthis->m_MutexCreater,INFINITE);
    48. if(pthis->nCount>=100)
    49. {
    50. ReleaseMutex( pthis->m_MutexConsumer);
    51. continue;
    52. }
    53. //pthis->product++;
    54. InterlockedIncrement(&pthis->product);
    55. InterlockedIncrement(&pthis->nCount);
    56. cout<nCount<
    57. ReleaseMutex(pthis->m_MutexConsumer);
    58. }
    59. }
    60. }
    61. DWORD WINAPI CreaterConsumer::ConsumerThreadProc(LPVOID lpvoid)
    62. {
    63. CreaterConsumer* pthis=(CreaterConsumer*)lpvoid;
    64. while(1)
    65. {
    66. if(pthis->nCount<100)
    67. {
    68. WaitForSingleObject(pthis->m_MutexConsumer,INFINITE);
    69. if(pthis->nCount>=100)
    70. {
    71. ReleaseMutex( pthis->m_MutexCreater);
    72. continue;
    73. }
    74. //pthis->product--;
    75. InterlockedDecrement(&pthis->product);
    76. ReleaseMutex(pthis->m_MutexCreater);
    77. }
    78. }
    79. }
    80. void CreaterConsumer::DeleteCreaterThreadPool()
    81. {
    82. auto ite= m_myCreaterlist.begin();
    83. while(ite!=m_myCreaterlist.end())
    84. {
    85. delete *ite;
    86. ite++;
    87. }
    88. m_myCreaterlist.clear();
    89. if(m_Create)
    90. {
    91. CloseHandle(m_Create);
    92. m_Create=NULL;
    93. }
    94. if(m_MutexCreater)
    95. {
    96. CloseHandle(m_MutexCreater);
    97. m_MutexCreater=NULL;
    98. }
    99. }
    100. void CreaterConsumer::DeleteConsumerThreadPool()
    101. {
    102. auto ite= m_myConsumerlist.begin();
    103. while(ite!=m_myConsumerlist.end())
    104. {
    105. delete *ite;
    106. ite++;
    107. }
    108. if(m_Consumer)
    109. {
    110. CloseHandle(m_Consumer);
    111. m_Consumer=NULL;
    112. }
    113. if(m_MutexConsumer)
    114. {
    115. CloseHandle(m_MutexConsumer);
    116. m_MutexConsumer=NULL;
    117. }
    118. }

    执行结果

    交互次数为100 

  • 相关阅读:
    Pyhon中利用GM(1,1)和ARIMA模型对卫星DCB值进行预测
    极简的MapReduce实现
    02|一条MySQL更新语句是如何执行的
    @Transactional 的使用
    小谈设计模式(6)—依赖倒转原则
    安全工具--- rengine安装---资产侦查漏洞扫描
    第十四届蓝桥杯模拟赛(第二期)——C语言版
    Web请求与响应(SpringBoot)
    2023数学建模国赛选题建议及BC题思路
    Today‘s web RPC案例
  • 原文地址:https://blog.csdn.net/van9527/article/details/126224488