web-dev-qa-db-fra.com

Sémaphore - Quelle est l'utilisation du compte initial?

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

Pour créer un sémaphore, je dois fournir un nombre initial et un nombre maximal. MSDN indique qu'un compte initial est - 

Le nombre initial de demandes pour le sémaphore pouvant être accordé en même temps.

Bien qu’il indique que le compte maximum est 

Le nombre maximum de demandes pour le sémaphore pouvant être accordé en même temps.

Je peux comprendre que le nombre maximum est le nombre maximum de threads pouvant accéder simultanément à une ressource. Mais à quoi sert le compte initial? 

Si je crée un sémaphore avec un nombre initial de 0 et un nombre maximal de 2, aucun de mes thread threadpool ne peut accéder à la ressource. Si je fixe le nombre initial à 1 et le nombre maximal à 2, seul le thread de pool de threads peut accéder à la ressource. Ce n'est que lorsque je règle à la fois le compte initial et le compte maximum sur 2, 2 threads peuvent accéder à la ressource simultanément. Donc, je suis vraiment confus quant à la signification du décompte initial?

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
64
Sandbox

Oui, lorsque le nombre initial est défini sur 0, tous les threads attendent pendant que vous incrémentez la propriété "CurrentCount". Vous pouvez le faire avec Release () ou Release (Int32).

Release (...) - incrémentera le compteur de sémaphores

Attendez (...) - le décrémentera 

Vous ne pouvez pas incrémenter le compteur (propriété "CurrentCount") supérieur au nombre maximal que vous avez défini lors de l'initialisation.

Par exemple:

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()
57
SVGreg

Donc, je suis vraiment confus quant à la signification du décompte initial?

Un point important qui peut aider ici est que Wait décrémente le nombre de sémaphores et que Release l’incrémente.

initialCount est le nombre d'accès aux ressources qui seront autorisés immédiatement. Ou, en d'autres termes, c'est le nombre de fois que Wait peut être appelé sans blocage immédiatement après l'instanciation du sémaphore.

maximumCount est le nombre le plus élevé que le sémaphore puisse obtenir. C'est le nombre de fois que Release peut être appelé sans lever d'exception en supposant que initialCount count était égal à zéro. Si initialCount a la même valeur que maximumCount, l'appel de Release immédiatement après l'instanciation du sémaphore lève une exception.

44
Brian Gideon

Combien de threads voulez-vous pouvoir accéder à la ressource en même temps? Définissez votre nombre initial à ce nombre. Si ce nombre ne va jamais augmenter pendant toute la durée du programme, définissez également votre nombre maximal sur ce nombre. Ainsi, si vous avez une erreur de programmation dans la manière dont vous libérez la ressource, votre programme se bloquera et vous le fera savoir.

(Il existe deux constructeurs: l'un n'utilise qu'une valeur initiale et l'autre, le nombre maximal. Utilisez celui qui convient.)

5
Karmastan

Si vous souhaitez qu'aucun thread n'accède à votre ressource pendant un certain temps, vous transmettez le nombre initial à 0 et lorsque vous souhaitez accorder l'accès à tous après la création du sémaphore, vous transmettez la valeur du nombre initial égale au nombre maximal. . Par exemple:

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

Comme indiqué dans la documentation MSDN - «Une autre utilisation de ReleaseSemaphore est lors de l'initialisation d'une application. L'application peut créer un sémaphore avec un compte initial égal à zéro. Ceci définit l'état du sémaphore sur non-signalé et bloque l'accès à la ressource protégée par tous les threads. termine son initialisation, il utilise ReleaseSemaphore pour augmenter le nombre à sa valeur maximale, pour permettre un accès normal à la ressource protégée. "

1
Abhineet

Les sémaphores peuvent être utilisés pour protéger un pool de ressources . Nous utilisons des pools de ressources pour réutiliser des éléments qui sont coûteux à créer - tels que les connexions à une base de données. 

Ainsi, le nombre initial fait référence au nombre de ressources disponibles dans le pool au début de chaque processus. Lorsque vous lisez la variable initialCount dans le code, vous devez penser aux efforts que vous déployez en amont pour créer ce pool de ressources. 

Je suis vraiment confus quant à la signification du décompte initial?

Initial count = Upfront cost

En tant que tel, en fonction du profil d'utilisation de votre application, cette valeur peut avoir un effet considérable sur les performances de votre application. Ce n'est pas juste un nombre arbitraire. 

Vous devez bien réfléchir à ce que vous créez, à leur coût de création et au nombre dont vous avez immédiatement besoin. Vous devriez littéralement être capable de représenter graphiquement la valeur optimale pour ce paramètre et devriez probablement penser à le rendre configurable de manière à pouvoir adapter les performances du processus à son heure d'exécution.

1
rism

Ainsi, lorsque le thread en cours crée le sémaphore, il peut réclamer des ressources dès le début.

1
Erno de Weerd

As MSDN l'explique dans la section Remarques:

Si initialCount est inférieur à maximumCount, l'effet est le même que si le thread actuel avait appelé WaitOne (maximumCount moins initialCount) fois. Si vous ne souhaitez réserver aucune entrée pour le thread qui crée le sémaphore, utilisez le même nombre pour maximumCount et initialCount.

Ainsi, si le nombre initial est 0 et le nombre maximal est 2, c'est comme si WaitOne avait été appelé deux fois par le thread principal. Nous avons donc atteint la capacité maximale (le nombre de sémaphores est égal à 0) et aucun thread ne peut entrer dans Semaphore. De même, si le nombre initial est 1 et que le nombre maximum est 2, WaitOnce a été appelé une fois et un seul thread peut entrer avant que nous n'atteignions de nouveau la capacité, et ainsi de suite. 

Si 0 est utilisé pour le nombre initial, nous pouvons toujours appeler Release (2) pour augmenter le nombre de sémaphores au maximum et permettre au nombre maximal de threads d'acquérir des ressources. 

0
Irfan