c++多线程学习7信号

多线程同步之Semaphore (主要用来解决生产者/消费者问题)

一 信标Semaphore
信标内核对象用于对资源进行计数。它们与所有内核对象一样,包含一个使用数量,但是它们也包含另外两个带符号的3 2位值,一个是最大资源数量,一个是当前资源数量。最大资源数量用于标识信标能够控制的资源的最大数量,而当前资源数量则用于标识当前可以使用的资源的数量。

为了正确地说明这个问题,让我们来看一看应用程序是如何使用信标的。比如说,我正在开发一个服务器进程,在这个进程中,我已经分配了一个能够用来存放客户机请求的缓冲区。我对缓冲区的大小进行了硬编码,这样它每次最多能够存放5个客户机请求。如果5个请求尚未处理完毕时,一个新客户机试图与服务器进行联系,那么这个新客户机的请求就会被拒绝,并出现一个错误,指明服务器现在很忙,客户机应该过些时候重新进行联系。当我的服务器进程初始化时,它创建一个线程池,里面包含5个线程,每个线程都准备在客户机请求到来时对它进行处理。

开始时,没有客户机提出任何请求,因此我的服务器不允许线程池中的任何线程成为可调度线程。但是,如果3个客户机请求同时到来,那么线程池中应该有3个线程处于可调度状态。使用信标,就能够很好地处理对资源的监控和对线程的调度,最大资源数量设置为5,因为这是我进行硬编码的缓冲区的大小。当前资源数量最初设置为0,因为没有客户机提出任何请求。当客户机的请求被接受时,当前资源数量就递增,当客户机的请求被提交给服务器的线程池时,当前资源数量就递减。

信标的使用规则如下:

• 如果当前资源的数量大于0,则发出信标信号。

• 如果当前资源数量是0,则不发出信标信号。

• 系统决不允许当前资源的数量为负值。

• 当前资源数量决不能大于最大资源数量。

当使用信标时,不要将信标对象的使用数量与它的当前资源数量混为一谈。

二 APISemaphore function Description
CreateSemaphore Creates or opens a named or unnamed semaphore object.
CreateSemaphoreEx Creates or opens a named or unnamed semaphore object and returns a handle to the object.
OpenSemaphore Opens an existing named semaphore object.
ReleaseSemaphore Increases the count of the specified semaphore object by a specified amount.


三 实例
#include <windows.h>
#include <stdio.h>

#define MAX_SEM_COUNT 6
#define THREADCOUNT 12

HANDLE ghSemaphore;

DWORD WINAPI ThreadProc( LPVOID );

void main()
{
  HANDLE aThread[THREADCOUNT];
  DWORD ThreadID;
  int i;

  // Create a semaphore with initial and max counts of MAX_SEM_COUNT

  ghSemaphore = CreateSemaphore( 
  NULL, // default security attributes
  MAX_SEM_COUNT, // initial count
  MAX_SEM_COUNT, // maximum count
  NULL); // unnamed semaphore

  if (ghSemaphore == NULL) 
  {
  printf("CreateSemaphore error: %d/n", GetLastError());
  return;
  }

  // Create worker threads

  for( i=0; i < THREADCOUNT; i++ )
  {
  aThread[i] = CreateThread( 
  NULL, // default security attributes
  0, // default stack size
  (LPTHREAD_START_ROUTINE) ThreadProc, 
  NULL, // no thread function arguments
  0, // default creation flags
  &ThreadID); // receive thread identifier

  if( aThread[i] == NULL )
  {
  printf("CreateThread error: %d/n", GetLastError());
  return;
  }
  }

  // Wait for all threads to terminate

  WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);

  // Close thread and semaphore handles

  for( i=0; i < THREADCOUNT; i++ )
  CloseHandle(aThread[i]);

  CloseHandle(ghSemaphore);
}

DWORD WINAPI ThreadProc( LPVOID lpParam )
{
  DWORD dwWaitResult; 
  BOOL bContinue=TRUE;

  while(bContinue)
  {
  // Try to enter the semaphore gate.

  dwWaitResult = WaitForSingleObject( 
  ghSemaphore, // handle to semaphore
  3L); // zero-second time-out interval

  switch (dwWaitResult) 
  { 
  // The semaphore object was signaled.
  case WAIT_OBJECT_0: 
  // TODO: Perform task
  printf("Thread %d: wait succeeded/n", GetCurrentThreadId());
  bContinue=FALSE;  

  // Simulate thread spending time on task
  Sleep(5);

  for(int x = 0; x< 10; x++)
  printf("Thread %d task!/n",GetCurrentThreadId());

  // Relase the semaphore when task is finished

  if (!ReleaseSemaphore( 
  ghSemaphore, // handle to semaphore
  1, // increase count by one
  NULL) ) // not interested in previous count
  {
  printf("ReleaseSemaphore error: %d/n", GetLastError());
  }
  break; 

  // The semaphore was nonsignaled, so a time-out occurred.
  case WAIT_TIMEOUT: 
  printf("Thread %d: wait timed out/n", GetCurrentThreadId());
  break; 
  }
  }
  return TRUE;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值