Semaphore Objects

Semaphore Objects


A semaphore object is a synchronization object that maintains a count between zero and a specified maximum value. 
The count is decremented each time a thread completes a wait for the semaphore object and incremented each time a thread releases the semaphore. 
When the count reaches zero, no more threads can successfully wait for the semaphore object state to become signaled. 
The state of a semaphore is set to signaled when its count is greater than zero, and nonsignaled when its count is zero.
Semaphone Object(信号量)是一个同步对象。Semaphone Object 包含一个从零到指定最大值的计数值。
当一个线程获取到Semaphone的权利时,计数值将减少1,当线程释放Semaphone权利时计数值增加一.当Semaphone Object的计数值到零时,任何线程都不能获取到Semaphone Object的权利.
当计数值大于零时,Semaphone Object标志着有信号,当Semaphone Object的计数值等于零时,标志着无信号。




The semaphore object is useful in controlling a shared resource that can support a limited number of users.
It acts as a gate that limits the number of threads sharing the resource to a specified maximum number. 
For example, an application might place a limit on the number of windows that it creates. 
It uses a semaphore with a maximum count equal to the window limit, decrementing the count whenever a window is created and incrementing it whenever a window is closed. 
The application specifies the semaphore object in call to one of the wait functions before each window is created. 
When the count is zero—indicating that the window limit has been reached—the wait function blocks execution of the window-creation code.


Semaphone Object在控制有限数量的线程来并发访问共享资源非常有用。Semaphone Object就像一个门卫,只运行指定最大数量的线程来并发访问共享资源。
例如:应用程序可以在Windows创建资源上做一个指定的最大限制。
  
A thread uses the CreateSemaphore or CreateSemaphoreEx function to create a semaphore object. 
The creating thread specifies the initial count and the maximum value of the count for the object. 
The initial count must be neither less than zero nor greater than the maximum value. 
The creating thread can also specify a name for the semaphore object.
Threads in other processes can open a handle to an existing semaphore object by specifying its name in a call to the OpenSemaphore function.
线程通过CreateSemaphore() 和CreateSemaphoreEx()来创建一个Semaphone Object.
创建线程将指定计数的一个初始化值和一个最大值。初始化值必须小于等于最大值。同时,线程也可以为Semaphone Object指定一个名字。
在其他进程中的任何线程都可以通过OpenSemaphore()函数传递一个名字参数到有名称的Semaphone Object 来获取该对象。
  
If more than one thread is waiting on a semaphore, a waiting thread is selected. Do not assume a first-in, first-out (FIFO) order.
External events such as kernel-mode APCs can change the wait order.
如果多个线程在等待同一个Semaphone Object,任意一个线程将被选中。不依赖于先进先出FIFL顺序。但是可以通过内核模式来改变排队的顺序。
Each time one of the wait functions returns because the state of a semaphore was set to signaled, the count of the semaphore is decreased by one.
The ReleaseSemaphore function increases a semaphore's count by a specified amount. The count can never be less than zero or greater than the maximum value.


wait等待函数返回时,Semaphone Object 的状态将被设置成有信号,同时计数值也被减少1.线程可以通过ReleaseSemaphore()函数来增加计数值。但是,计数值必须不能小于零,不能大于最大值。
The initial count of a semaphore is typically set to the maximum value. 
The count is then decremented from that level as the protected resource is consumed. 
Alternatively, you can create a semaphore with an initial count of zero to block access to the protected resource while the application is being initialized.
After initialization, you can use ReleaseSemaphore to increment the count to the maximum value.


通常情况下,初始化值被设置成最大值。当被保护资源消耗时,计数值被减小1.也可以把初始值设置成零,这样在应用程序初始化时,等待的线程就会被阻塞从而保护共享资源。
初始化后,线程必须通过ReleaseSemaphore()函数来增加1.
A thread that owns a mutex object can wait repeatedly for the same mutex object to become signaled without its execution becoming blocked.
A thread that waits repeatedly for the same semaphore object, however, decrements the semaphore's count each time a wait operation is completed; 
the thread is blocked when the count gets to zero.
Similarly, only the thread that owns a mutex can successfully call the ReleaseMutex function, though any thread can use ReleaseSemaphore to increase the count of a semaphore object.
注意:注意:当一个拥有Mutex Object(互斥量)的线程重复调用等待函数,Mutex Object 依旧有信号,并且不会发生阻塞,这样可以防止自锁。
但是,当一个拥有Semaphone Object对象重复调用等待函数时,当等待函数完成时,Semaphone Object的计数量将减少1.当同一线程多次调用同一个Semaphone Object时,当计数量为零时,就会发生阻塞。




A thread can decrement a semaphore's count more than once by repeatedly specifying the same semaphore object in calls to any of the wait functions. 
However, calling one of the multiple-object wait functions with an array that contains multiple handles of the same semaphore does not result in multiple decrements.


When you have finished using the semaphore object, call the CloseHandle function to close the handle. 
The semaphore object is destroyed when its last handle has been closed. 
Closing the handle does not affect the semaphore count; therefore, be sure to call ReleaseSemaphore before closing the handle or before the process terminates. 
Otherwise, pending wait operations will either time out or continue indefinitely, depending on whether a time-out value has been specified.
当结束使用Semaphone Object时,可以通过CloseHandle()来释放Semaphone Object.
关闭Semaphone Object时,并不影响Semaphone Object的计数量。所有,必须确保关闭Semaphone Object时通过ReleaseSemaphore()函数减少计数量。

否则在等待期间的其他线程将超时或者无限期持续等待。

例子:UsingSemaphoreObjects.cpp

#include <windows.h>
#include <stdio.h>

#define MAX_SEM_COUNT 5
#define THREADCOUNT 10

HANDLE ghSemaphore;

DWORD WINAPI ThreadProc( LPVOID );

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

    // Create a semaphore with initial and max counts of MAX_SEM_COUNT
	//创建一个信号量,初始值和最大值相等,这样就运行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 1;
    }

    // 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 1;
        }
    }

    // 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]);
	printf("=====================================: %d\n", GetCurrentThreadId());
	//当前主线程可以多次获取Metux Object,但是最大只能获取到MAX_SEM_COUNT 次数
	for(size_t t =0;t<MAX_SEM_COUNT*2;t++)
	{
			 // Try to enter the semaphore gate.

         DWORD dwWaitResult = WaitForSingleObject( 
            ghSemaphore,   // handle to semaphore
            0L);           // zero-second time-out interval
        switch (dwWaitResult) 
        { 
            // The semaphore object was signaled.
            case WAIT_OBJECT_0: 
				    printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
                break; 
			      // The semaphore was nonsignaled, so a time-out occurred.
            case WAIT_TIMEOUT: 
                printf("Thread %d: wait timed out\n", GetCurrentThreadId());
                break; 
		}
	}

    CloseHandle(ghSemaphore);

    return 0;
}

DWORD WINAPI ThreadProc( LPVOID lpParam )
{

    // lpParam not used in this example
    UNREFERENCED_PARAMETER(lpParam);

    DWORD dwWaitResult; 
    BOOL bContinue=TRUE;

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

        dwWaitResult = WaitForSingleObject( 
            ghSemaphore,   // handle to semaphore
            0L);           // 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);

                // Release 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;
}

运行结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值