信号量 – 初始计数有什么用?

http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.aspx

要创build一个信号量,我需要提供一个初始计数和最大计数。 MSDN指出,最初的计数是 –

可以同时授予的信号量请求的初始数量。

虽然它说最大的数量是

可以同时授予的信号量的最大请求数。

我可以理解,最大数量是可以并发访问资源的最大线程数。 但是,什么是初始计数的使用?

如果我创build一个初始计数为0和最大计数为2的信号量,则不会有任何线程池线程能够访问资源。 如果我将初始计数设置为1,最大计数设置为2,则只有线程池线程可以访问资源。 只有当初始计数和最大计数都设置为2时,2个线程才能够同时访问资源。 那么,我真的很疑惑初始计数的意义呢?

SemaphoreSlim semaphoreSlim = new SemaphoreSlim(0, 2); //all threadpool threads wait SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 2);//only one thread has access to the resource at a time SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2, 2);//two threadpool threads can access the resource concurrently 

是的,当初始数字设置为0 – 所有线程将等待,而你增加“CurrentCount”属性。 你可以用Release()或Release(Int32)来完成。

释放(…) – 将增加信号量计数器

等待(…) – 将递减

您不能递增计数器(“CurrentCount”属性)大于您在初始化中设置的最大计数。

例如:

 SemaphoreSlim^ s = gcnew SemaphoreSlim(0,2); //s->CurrentCount = 0 s->Release(2); //s->CurrentCount = 2 ... s->Wait(); //Ok. s->CurrentCount = 1 ... s->Wait(); //Ok. s->CurrentCount = 0 ... s->Wait(); //Will be blocked until any of the threads calls Release() 

那么,我真的很疑惑初始计数的意义呢?

在这里可能有帮助的一个重要的一点是Wait递减信号计数并且递增递增它。

initialCount是立即允许的资源访问次数。 或者换句话说,信号量被实例化后, Wait的次数可以被立即调用而不会立即被阻塞。

maximumCount是信号量可以获得的最高计数。 如果initialCount计数为零,则可以在不引发exception的情况下调用Release次数。 如果initialCount设置为与maximumCount相同的值,那么在实例化信号量后立即调用Release将引发exception。

您希望一次能够访问多less个线程? 将您的初始计数设置为该数字。 如果这个数字在程序的整个生命周期中都不会增加,那么也要把这个数字设置为这个数字。 这样,如果您在释放资源的过程中遇到编程错误,那么您的程序将会崩溃并通知您。

(有两个构造函数:一个只取一个初始值,另一个取最大值,使用适当的值。

这样当当前线程创build信号量时,它可以从一开始就声明一些资源。

如果你希望没有线程访问你的资源一段时间,你将初始计数设置为0,当你希望在创build信号量之后授予对它们全部的访问权限时,将初始计数值等于最大计数。 例如:

 hSemaphore = CreateSemaphoreA(NULL, 0, MAX_COUNT, NULL) ; //Do something here //No threads can access your resource ReleaseSemaphore(hSemaphore, MAX_COUNT, 0) ; //All threads can access the resource now 

正如MSDN文档中所引用的:“ReleaseSemaphore的另一个用途是在应用程序初始化期间,应用程序可以创build一个初始计数为零的信号量,这将信号量的状态设置为非信号并阻止所有线程访问受保护的资源。完成其初始化,它使用ReleaseSemaphore将计数增加到其最大值,以允许正常访问受保护的资源。

正如MSDN在备注部分所解释的那样:

如果initialCount小于maximumCount,则效果与当前线程调用WaitOne(maximumCount minus initialCount)次数相同。 如果您不想为创build信号量的线程保留任何条目,请为maximumCount和initialCount使用相同的数字。

所以,如果初始计数是0,最大值是2,就好像WaitOne被主线程调用了两次,所以我们已经达到了容量(现在信号计数为0),没有线程可以进入信号量。 类似地,如果初始计数为1且最大为2,则WaitOnce被调用一次,只有一个线程可以进入,然后再次达到容量,等等。

如果0用于初始计数,我们总是可以调用Release(2)将信号量计数增加到最大值,以允许最大数量的线程获取资源。