zoukankan      html  css  js  c++  java
  • 生产者消费者问题

    参考地址:http://blog.csdn.net/morewindows/article/details/7577591

    生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将它生产的产品放入一个缓冲区中,消费者可以从缓冲区中取走产品进行消费,显然生产者和消费者之间必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个已经放入产品的缓冲区中再次投放产品。

    代码一:1个生产者,1个消费者,1个缓冲区

     1 #include <iostream>
     2 #include <Windows.h>
     3 #include <process.h>
     4 using namespace std;
     5 /************************************************************************************
     6 
     7                             模拟单个缓冲区的情况
     8 
     9 *************************************************************************************/
    10 const int PRODUCT_NUM = 10; //生产产品个数
    11 int g_nBuffer;                //缓冲区
    12 CRITICAL_SECTION g_cs;
    13 HANDLE g_hEventBufferEmpty;
    14 HANDLE g_hEventBufferFull;
    15 
    16 //设置控制台文字颜色
    17 BOOL SetConsoleColor(WORD wAttributes)
    18 {
    19     HANDLE hHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    20     if (hHandle == INVALID_HANDLE_VALUE)
    21     {
    22         cout << "GetStdHandle Error!" << endl;
    23         return false;
    24     }
    25     //SetConsoleTitle(L"生产者消费者问题");
    26     return SetConsoleTextAttribute(hHandle, wAttributes);
    27 }
    28 
    29 unsigned int WINAPI ProducerThreadFunc(PVOID pParam)
    30 {
    31     for (int i = 1; i <= PRODUCT_NUM; ++i)
    32     {
    33         if (i > PRODUCT_NUM)
    34         {
    35             return 0;
    36         }
    37         WaitForSingleObject(g_hEventBufferEmpty, INFINITE);
    38         EnterCriticalSection(&g_cs);
    39         g_nBuffer = i;
    40         SetConsoleColor(FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED);
    41         cout << "生产者将数据[" << i << "]放入缓冲区!" << endl;
    42         LeaveCriticalSection(&g_cs);
    43         SetEvent(g_hEventBufferFull);
    44     }
    45     return 0;
    46 }
    47 
    48 unsigned int WINAPI ConsumerThreadFunc(PVOID pParam)
    49 {
    50     //volatile bool bFlag = true;
    51     while(true)
    52     {
    53         WaitForSingleObject(g_hEventBufferFull, INFINITE);
    54         EnterCriticalSection(&g_cs);
    55         SetConsoleColor(FOREGROUND_GREEN);
    56         cout << "消费者从缓冲区中取出数据[" << g_nBuffer << "]" << endl;
    57         SetConsoleColor(FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN);
    58         if (g_nBuffer == PRODUCT_NUM)
    59         {
    60             LeaveCriticalSection(&g_cs);
    61             return 0;
    62         }
    63         Sleep(100);
    64         LeaveCriticalSection(&g_cs);
    65         SetEvent(g_hEventBufferEmpty);
    66     }
    67     return 0;
    68 }
    69 
    70 int main()
    71 {
    72     const int nThreadNum = 2;
    73     HANDLE hThread[nThreadNum];
    74     g_hEventBufferEmpty = CreateEvent(NULL, false, true, NULL);
    75     g_hEventBufferFull = CreateEvent(NULL, false, false, NULL);
    76     InitializeCriticalSection(&g_cs);
    77 
    78     cout << "		生产者消费者问题:1生产者,1消费者,1缓冲区" << endl;
    79     hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFunc, NULL, 0, NULL);
    80     hThread[1] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFunc, NULL, 0, NULL);
    81     WaitForMultipleObjects(nThreadNum, hThread, true, INFINITE);
    82     
    83     CloseHandle(hThread[0]);
    84     CloseHandle(hThread[1]);
    85     CloseHandle(g_hEventBufferFull);
    86     CloseHandle(g_hEventBufferEmpty);
    87     DeleteCriticalSection(&g_cs);
    88 
    89     return 0;
    90 }

    代码二:1个生成者,2个消费者,4个缓冲区

      1 #include <iostream>
      2 #include <Windows.h>
      3 #include <process.h>
      4 using namespace std;
      5 /************************************************************************************
      6 
      7                         模拟多个缓冲区、多个消费者的情况
      8 
      9 *************************************************************************************/
     10 const int PRODUCT_NUM = 10; //生产产品个数
     11 const int BUFFERSIZE = 4;    //缓冲区个数
     12 int g_nBuffer[BUFFERSIZE];
     13 int g_nProduceCnt;    //生产位置
     14 int g_nConsumeCnt;    //消费位置
     15 CRITICAL_SECTION g_cs;
     16 HANDLE g_hSemaphoreEmpty;
     17 HANDLE g_hSemaphoreFull;
     18 
     19 //设置控制台文字颜色
     20 BOOL SetConsoleColor(WORD wAttributes)
     21 {
     22     HANDLE hHandle = GetStdHandle(STD_OUTPUT_HANDLE);
     23     if (hHandle == INVALID_HANDLE_VALUE)
     24     {
     25         cout << "GetStdHandle Error!" << endl;
     26         return false;
     27     }
     28     //SetConsoleTitle(L"生产者消费者问题");
     29     return SetConsoleTextAttribute(hHandle, wAttributes);
     30 }
     31 
     32 unsigned int WINAPI ProducerThreadFunc(PVOID pParam)
     33 {
     34     for (int i = 1; i <= PRODUCT_NUM; ++i)
     35     {//生产者与消费者之间本不应该互斥,但是这里考虑到设置控制台颜色的问题,必须互斥,实际情况这里的互斥条件应该去掉
     36         WaitForSingleObject(g_hSemaphoreEmpty, INFINITE);
     37         EnterCriticalSection(&g_cs);
     38         g_nProduceCnt = (i-1)%BUFFERSIZE;
     39         g_nBuffer[g_nProduceCnt] = i;
     40         SetConsoleColor(FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED);
     41         cout << "生产者[" << GetCurrentThreadId() << "]将数据[" << i << "]放入缓冲区位置[" << g_nProduceCnt << "]" << endl;
     42         LeaveCriticalSection(&g_cs);
     43         ReleaseSemaphore(g_hSemaphoreFull, 1, NULL);
     44     }
     45     return 0;
     46 }
     47 
     48 unsigned int WINAPI ConsumerThreadFunc(PVOID pParam)
     49 {
     50     volatile bool bFlag = true;
     51     while(bFlag)
     52     {
     53         WaitForSingleObject(g_hSemaphoreFull, INFINITE);
     54         EnterCriticalSection(&g_cs);
     55         if (!bFlag)
     56         {
     57             LeaveCriticalSection(&g_cs);
     58             return 0;
     59         }
     60         SetConsoleColor(FOREGROUND_GREEN);
     61         cout << "消费者[" << GetCurrentThreadId() << "]从缓冲区中位置[" << g_nConsumeCnt%BUFFERSIZE << "]取出数据[" << 
                    g_nBuffer[g_nConsumeCnt%BUFFERSIZE] << "]" << endl; 62 ++g_nConsumeCnt; 63 SetConsoleColor(FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_GREEN); 64 if (g_nConsumeCnt == PRODUCT_NUM) 65 { 66 LeaveCriticalSection(&g_cs); 67 bFlag = false; 68 } 69 Sleep(100); 70 LeaveCriticalSection(&g_cs); 71 ReleaseSemaphore(g_hSemaphoreEmpty, 1, NULL); 72 } 73 return 0; 74 } 75 76 int main() 77 { 78 const int nThreadNum = 3; 79 HANDLE hThread[nThreadNum]; 80 81 g_hSemaphoreEmpty = CreateSemaphore(NULL, 4, BUFFERSIZE, NULL); 82 g_hSemaphoreFull = CreateSemaphore(NULL, 0, BUFFERSIZE, NULL); 83 InitializeCriticalSection(&g_cs); 84 85 g_nProduceCnt = 0; 86 g_nConsumeCnt = 0; 87 cout << " 生产者消费者问题:1生产者,2消费者,4缓冲区" << endl; 88 hThread[0] = (HANDLE)_beginthreadex(NULL, 0, ProducerThreadFunc, NULL, 0, NULL); 89 hThread[1] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFunc, NULL, 0, NULL); 90 hThread[2] = (HANDLE)_beginthreadex(NULL, 0, ConsumerThreadFunc, NULL, 0, NULL); 91 WaitForMultipleObjects(nThreadNum, hThread, true, INFINITE); 92 93 for (int i = 0; i < nThreadNum; ++i) 94 CloseHandle(hThread[i]); 95 CloseHandle(g_hSemaphoreFull); 96 CloseHandle(g_hSemaphoreEmpty); 97 DeleteCriticalSection(&g_cs); 98 99 return 0; 100 }
  • 相关阅读:
    差分约束系统
    LCA
    CRB and Candies LCM 性质
    【强连通分量】 Kosaraju和Tarjan算法 (标准模板+详细注释)
    最小生成树
    堆优化的迪杰斯特拉算法
    SPFA算法
    Floyd算法
    Dijkstra算法
    图论中环的判断
  • 原文地址:https://www.cnblogs.com/dongsheng/p/5085163.html
Copyright © 2011-2022 走看看