• Windows线程(生产者与消费者问题)


    Windows线程(生产者与消费者问题) 转载 佟强 2008.10.10

         生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

    1. #include <windows.h> 
    2. #include <iostream> 
    3. const unsigned short SIZE_OF_BUFFER = 10; //缓冲区长度 
    4. unsigned short ProductID = 0; //产品号 
    5. unsigned short ConsumeID = 0; //将被消耗的产品号 
    6. unsigned short in = 0; //产品进缓冲区时的缓冲区下标 
    7. unsigned short out = 0; //产品出缓冲区时的缓冲区下标 
    8. int g_buffer[SIZE_OF_BUFFER]; //缓冲区是个循环队列 
    9. bool g_continue = true//控制程序结束 
    10. HANDLE g_hMutex; //用于线程间的互斥 
    11. HANDLE g_hFullSemaphore; //当缓冲区满时迫使生产者等待 
    12. HANDLE g_hEmptySemaphore; //当缓冲区空时迫使消费者等待 
    13. DWORD WINAPI Producer(LPVOID); //生产者线程 
    14. DWORD WINAPI Consumer(LPVOID); //消费者线程 
    15. int main() 
    16.  //创建各个互斥信号 
    17.  g_hMutex = CreateMutex(NULL,FALSE,NULL); 
    18.  g_hFullSemaphore = CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL); 
    19.  g_hEmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL); 
    20.  //调整下面的数值,可以发现,当生产者个数多于消费者个数时, 
    21.  //生产速度快,生产者经常等待消费者;反之,消费者经常等待 
    22.  const unsigned short PRODUCERS_COUNT = 3; //生产者的个数 
    23.  const unsigned short CONSUMERS_COUNT = 1; //消费者的个数 
    24.  //总的线程数 
    25.  const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT; 
    26.  HANDLE hThreads[PRODUCERS_COUNT]; //各线程的handle 
    27.  DWORD producerID[CONSUMERS_COUNT]; //生产者线程的标识符 
    28.  DWORD consumerID[THREADS_COUNT]; //消费者线程的标识符 
    29.  //创建生产者线程 
    30.  for (int i=0;i<PRODUCERS_COUNT;++i){ 
    31.   hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]); 
    32.   if (hThreads[i]==NULL) return -1; 
    33.  } 
    34.  //创建消费者线程 
    35.  for (int i=0;i<CONSUMERS_COUNT;++i){ 
    36.   hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]); 
    37.   if (hThreads[i]==NULL) return -1; 
    38.  } 
    39.  while(g_continue){ 
    40.   if(getchar()){ //按回车后终止程序运行 
    41.    g_continue = false
    42.   } 
    43.  } 
    44.  return 0; 
    45. //生产一个产品。简单模拟了一下,仅输出新产品的ID号 
    46. void Produce() 
    47.  std::cerr << "Producing " << ++ProductID << " ... "
    48.  std::cerr << "Succeed" << std::endl; 
    49. //把新生产的产品放入缓冲区 
    50. void Append() 
    51.  std::cerr << "Appending a product ... "
    52.  g_buffer[in] = ProductID; 
    53.  in = (in+1)%SIZE_OF_BUFFER; 
    54.  std::cerr << "Succeed" << std::endl; 
    55.  //输出缓冲区当前的状态 
    56.  for (int i=0;i<SIZE_OF_BUFFER;++i){ 
    57.   std::cout << i <<": " << g_buffer[i]; 
    58.   if (i==in) std::cout << " <-- 生产"
    59.   if (i==out) std::cout << " <-- 消费"
    60.   std::cout << std::endl; 
    61.  } 
    62. //从缓冲区中取出一个产品 
    63. void Take() 
    64.  std::cerr << "Taking a product ... "
    65.  ConsumeID = g_buffer[out]; 
    66.  out = (out+1)%SIZE_OF_BUFFER; 
    67.  std::cerr << "Succeed" << std::endl; 
    68.  //输出缓冲区当前的状态 
    69.  for (int i=0;i<SIZE_OF_BUFFER;++i){ 
    70.   std::cout << i <<": " << g_buffer[i]; 
    71.   if (i==in) std::cout << " <-- 生产"
    72.   if (i==out) std::cout << " <-- 消费"
    73.   std::cout << std::endl; 
    74.  } 
    75. //消耗一个产品 
    76. void Consume() 
    77.  std::cerr << "Consuming " << ConsumeID << " ... "
    78.  std::cerr << "Succeed" << std::endl; 
    79. //生产者 
    80. DWORD WINAPI Producer(LPVOID lpPara) 
    81.  while(g_continue){ 
    82.   WaitForSingleObject(g_hFullSemaphore,INFINITE); 
    83.   WaitForSingleObject(g_hMutex,INFINITE); 
    84.   Produce(); 
    85.   Append(); 
    86.   Sleep(1500); 
    87.   ReleaseMutex(g_hMutex); 
    88.   ReleaseSemaphore(g_hEmptySemaphore,1,NULL); 
    89.  } 
    90.  return 0; 
    91. //消费者 
    92. DWORD WINAPI Consumer(LPVOID lpPara) 
    93.  while(g_continue){ 
    94.   WaitForSingleObject(g_hEmptySemaphore,INFINITE); 
    95.   WaitForSingleObject(g_hMutex,INFINITE); 
    96.   Take(); 
    97.   Consume(); 
    98.   Sleep(1500); 
    99.   ReleaseMutex(g_hMutex); 
    100.   ReleaseSemaphore(g_hFullSemaphore,1,NULL); 
    101.  } 
    102.  return 0; 
    103. }   
  • 相关阅读:
    linux 环境变量 ($PATH)
    read()、write()返回 Input/output error, Device or resource busy解决
    初次尝试一个注册表
    CSS定位
    CSS中颜色代码和单位
    DOM和BOM
    java代码中获取classpath路径
    黑盒测试与白盒测试相比,哪个更难
    LoadRunner11遇到问题及解决办法
    Linux下修改日期和时间
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6168137.html
Copyright © 2020-2023  润新知