信号量 – 初始计数有什么用?
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)将信号量计数增加到最大值,以允许最大数量的线程获取资源。