多线程同步-信号量(深入理解Semaphore)

时间:2022-04-08 15:17:35

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

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

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

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

信标的使用规则如下:

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

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

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

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

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

二 API

Semaphore 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.

三 实例
多线程同步-信号量(深入理解Semaphore)#include  < windows.h >
多线程同步-信号量(深入理解Semaphore)#include 
< stdio.h >
多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)
#define  MAX_SEM_COUNT 6
多线程同步-信号量(深入理解Semaphore)
#define  THREADCOUNT 12
多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)HANDLE ghSemaphore;
多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)DWORD WINAPI ThreadProc( LPVOID );
多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)
void  main()
多线程同步-信号量(深入理解Semaphore)
{
多线程同步-信号量(深入理解Semaphore)    HANDLE aThread[THREADCOUNT];
多线程同步-信号量(深入理解Semaphore)    DWORD ThreadID;
多线程同步-信号量(深入理解Semaphore)    
int i;
多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)    
// Create semaphore with initial and max counts of MAX_SEM_COUNT
多线程同步-信号量(深入理解Semaphore)

多线程同步-信号量(深入理解Semaphore)    ghSemaphore 
= CreateSemaphore( 
多线程同步-信号量(深入理解Semaphore)        NULL,           
// default security attributes
多线程同步-信号量(深入理解Semaphore)
        MAX_SEM_COUNT,  // initial count
多线程同步-信号量(深入理解Semaphore)
        MAX_SEM_COUNT,  // maximum count
多线程同步-信号量(深入理解Semaphore)
        NULL);          // unnamed semaphore
多线程同步-信号量(深入理解Semaphore)

多线程同步-信号量(深入理解Semaphore)    
if (ghSemaphore == NULL) 
多线程同步-信号量(深入理解Semaphore)    
{
多线程同步-信号量(深入理解Semaphore)        printf(
"CreateSemaphore error: %d\n"GetLastError());
多线程同步-信号量(深入理解Semaphore)        
return;
多线程同步-信号量(深入理解Semaphore)    }

多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)    
// Create worker threads
多线程同步-信号量(深入理解Semaphore)

多线程同步-信号量(深入理解Semaphore)    
fori=0< THREADCOUNT; i++ )
多线程同步-信号量(深入理解Semaphore)    
{
多线程同步-信号量(深入理解Semaphore)        aThread[i] 
= CreateThread( 
多线程同步-信号量(深入理解Semaphore)                     NULL,       
// default security attributes
多线程同步-信号量(深入理解Semaphore)
                     0         // default stack size
多线程同步-信号量(深入理解Semaphore)
                     (LPTHREAD_START_ROUTINE) ThreadProc, 
多线程同步-信号量(深入理解Semaphore)                     NULL,       
// no thread function arguments
多线程同步-信号量(深入理解Semaphore)
                     0         // default creation flags
多线程同步-信号量(深入理解Semaphore)
                     &ThreadID); // receive thread identifier
多线程同步-信号量(深入理解Semaphore)

多线程同步-信号量(深入理解Semaphore)        
ifaThread[i] == NULL )
多线程同步-信号量(深入理解Semaphore)        
{
多线程同步-信号量(深入理解Semaphore)            printf(
"CreateThread error: %d\n"GetLastError());
多线程同步-信号量(深入理解Semaphore)            
return;
多线程同步-信号量(深入理解Semaphore)        }

多线程同步-信号量(深入理解Semaphore)    }

多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)    
// Wait for all threads to terminate
多线程同步-信号量(深入理解Semaphore)

多线程同步-信号量(深入理解Semaphore)    WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)    
// Close thread and semaphore handles
多线程同步-信号量(深入理解Semaphore)

多线程同步-信号量(深入理解Semaphore)    
fori=0< THREADCOUNT; i++ )
多线程同步-信号量(深入理解Semaphore)        CloseHandle(aThread[i]);
多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)    CloseHandle(ghSemaphore);
多线程同步-信号量(深入理解Semaphore)}

多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)DWORD WINAPI ThreadProc( LPVOID lpParam )
多线程同步-信号量(深入理解Semaphore)
{
多线程同步-信号量(深入理解Semaphore)    DWORD dwWaitResult; 
多线程同步-信号量(深入理解Semaphore)    BOOL bContinue
=TRUE;
多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)    
while(bContinue)
多线程同步-信号量(深入理解Semaphore)    
{
多线程同步-信号量(深入理解Semaphore)        
// Try to enter the semaphore gate.
多线程同步-信号量(深入理解Semaphore)

多线程同步-信号量(深入理解Semaphore)        dwWaitResult 
= WaitForSingleObject( 
多线程同步-信号量(深入理解Semaphore)            ghSemaphore,   
// handle to semaphore
多线程同步-信号量(深入理解Semaphore)
            3L);           // zero-second time-out interval
多线程同步-信号量(深入理解Semaphore)

多线程同步-信号量(深入理解Semaphore)        
switch (dwWaitResult) 
多线程同步-信号量(深入理解Semaphore)        

多线程同步-信号量(深入理解Semaphore)            
// The semaphore object was signaled.
多线程同步-信号量(深入理解Semaphore)
            case WAIT_OBJECT_0: 
多线程同步-信号量(深入理解Semaphore)                
// TODO: Perform task
多线程同步-信号量(深入理解Semaphore)
                printf("Thread %d: wait succeeded\n"GetCurrentThreadId());
多线程同步-信号量(深入理解Semaphore)                bContinue
=FALSE;            
多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)                
// Simulate thread spending time on task
多线程同步-信号量(深入理解Semaphore)
                Sleep(5);
多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)                
for(int = 0x< 10x++)
多线程同步-信号量(深入理解Semaphore)                    printf(
"Thread %d task!\n",GetCurrentThreadId());
多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)                
// Relase the semaphore when task is finished
多线程同步-信号量(深入理解Semaphore)

多线程同步-信号量(深入理解Semaphore)                
if (!ReleaseSemaphore( 
多线程同步-信号量(深入理解Semaphore)                        ghSemaphore,  
// handle to semaphore
多线程同步-信号量(深入理解Semaphore)
                        1           // increase count by one
多线程同步-信号量(深入理解Semaphore)
                        NULL)       // not interested in previous count
多线程同步-信号量(深入理解Semaphore)
                {
多线程同步-信号量(深入理解Semaphore)                    printf(
"ReleaseSemaphore error: %d\n"GetLastError());
多线程同步-信号量(深入理解Semaphore)                }

多线程同步-信号量(深入理解Semaphore)                
break
多线程同步-信号量(深入理解Semaphore)
多线程同步-信号量(深入理解Semaphore)            
// The semaphore was nonsignaled, so time-out occurred.
多线程同步-信号量(深入理解Semaphore)
            case WAIT_TIMEOUT: 
多线程同步-信号量(深入理解Semaphore)                printf(
"Thread %d: wait timed out\n"GetCurrentThreadId());
多线程同步-信号量(深入理解Semaphore)                
break
多线程同步-信号量(深入理解Semaphore)        }

多线程同步-信号量(深入理解Semaphore)    }

多线程同步-信号量(深入理解Semaphore)    
return TRUE;
多线程同步-信号量(深入理解Semaphore)}