web-dev-qa-db-fra.com

Différence entre le comptage et les sémaphores binaires

Quelle est la différence entre le comptage et le sémaphore binaire.

Ce que j'ai vu quelque part, c'est que les deux peuvent contrôler le nombre N de processus qui ont demandé une ressource. Les deux ont pris et les États libres.

Y a-t-il une restriction sur le nombre de ressources qu'un sémaphore binaire et un sémaphore de comptage peuvent protéger?

Les deux n'autorisent qu'un seul processus à utiliser une ressource à la fois ...

Y a-t-il une autre différence? Les propriétés mentionnées ci-dessus sont-elles correctes?

27
Umer Farooq

En fait, les deux types sont utilisés pour synchroniser l'accès à une ressource partagée, que l'entité qui tente d'accéder soit un processus ou même un thread.

La différence est la suivante:

Les sémaphores binaires sont binaires, ils ne peuvent avoir que deux valeurs; l'un pour indiquer qu'un processus/thread est dans la section critique (code qui accède à la ressource partagée) et d'autres doivent attendre, l'autre indiquant que la section critique est libre.

D'un autre côté, le comptage des sémaphores prend plus de deux valeurs, ils peuvent avoir n'importe quelle valeur souhaitée. La valeur maximale X qu'ils prennent permet à X processus/threads d'accéder simultanément à la ressource partagée.

Pour plus d'informations, consultez ce lien.
http://www.chibios.org/dokuwiki/doku.php?id=chibios:articles:semaphores_mutexes

[~ # ~] modifier [~ # ~]
La valeur maximale qu'un sémaphore de comptage peut prendre est le nombre de processus que vous souhaitez autoriser dans la section critique en même temps.
Encore une fois, vous pourriez avoir un cas où vous souhaitez exclure une certaine ressource, mais vous savez que cette ressource est accessible par un nombre maximum de processus (disons X), vous définissez donc un sémaphore de comptage avec la valeur X .

Cela permettrait aux processus X d'accéder simultanément à cette ressource; pourtant, le processus X + 1 devrait attendre jusqu'à ce que l'un des processus de la section critique sorte.

31
Fingolfin

Il existe deux concepts essentiels à la création de programmes simultanés: la synchronisation et l'exclusion mutuelle. Nous verrons comment ces deux types de verrous (les sémaphores sont plus généralement une sorte de mécanisme de verrouillage) nous aident à réaliser la synchronisation et l'exclusion mutuelle.

Un sémaphore se compose de deux parties: un compteur et une liste de tâches en attente d'accès à une ressource particulière. Un sémaphore effectue deux opérations: attendre (P) [c'est comme acquérir un verrou], et relâcher (V) [similaire à libérer un verrou] - ce sont les deux seules opérations que l'on peut effectuer sur un sémaphore. Dans un sémaphore binaire, le compteur va logiquement entre 0 et 1. Vous pouvez le considérer comme étant similaire à un verrou avec deux valeurs: ouvert/fermé. Un sémaphore de comptage a plusieurs valeurs pour le comptage.

Ce qui est important à comprendre, c'est que le compteur de sémaphores garde une trace du nombre de tâches qui n'ont pas à bloquer, c'est-à-dire qu'elles peuvent progresser. Les tâches se bloquent et ne s'ajoutent à la liste du sémaphore que lorsque le compteur est nul. Par conséquent, une tâche est ajoutée à la liste dans la routine P() si elle ne peut pas progresser et "libérée" à l'aide de la routine V().

Maintenant, il est assez évident de voir comment les sémaphores binaires peuvent être utilisés pour résoudre la synchronisation et l'exclusion mutuelle - ce sont essentiellement des verrous.

ex. Synchronisation:

thread A{
semaphore &s; //locks/semaphores are passed by reference! think about why this is so.
A(semaphore &s): s(s){} //constructor
foo(){
...
s.P();
;// some block of code B2
...
}

//thread B{
semaphore &s;
B(semaphore &s): s(s){} //constructor
foo(){
...
...
// some block of code B1
s.V();
..
}

main(){
semaphore s(0); // we start the semaphore at 0 (closed)
A a(s);
B b(s);
}

Dans l'exemple ci-dessus, B2 ne peut exécuter que après B1 a terminé son exécution. Disons que le thread A vient s'exécute en premier - arrive à sem.P (), et attend, puisque le compteur est 0 (fermé). Le fil B arrive, termine B1, puis libère le fil A - qui termine ensuite B2. Nous réalisons donc la synchronisation.

Examinons maintenant l'exclusion mutuelle avec un sémaphore binaire:

thread mutual_ex{
semaphore &s;
mutual_ex(semaphore &s): s(s){} //constructor
foo(){
...
s.P();
//critical section
s.V();
...
...
s.P();
//critical section
s.V();
...

}

main(){
semaphore s(1);
mutual_ex m1(s);
mutual_ex m2(s);
}

L'exclusion mutuelle est également assez simple - m1 et m2 ne peuvent pas entrer en même temps dans la section critique. Ainsi, chaque thread utilise le même sémaphore pour fournir une exclusion mutuelle pour ses deux sections critiques. Maintenant, est-il possible d'avoir une plus grande simultanéité? Dépend des sections critiques. (Réfléchissez à la façon dont on pourrait utiliser des sémaphores pour atteindre l'exclusion mutuelle. indice: ai-je nécessairement seulement besoin d'utiliser n sémaphore?)

Sémaphore de comptage: un sémaphore avec plus d'une valeur. Voyons ce que cela implique - un verrou avec plus d'une valeur? Donc ouvert, fermé et ... hmm. À quoi sert un verrouillage à plusieurs étages dans l'exclusion mutuelle ou la synchronisation?

Prenons le plus simple des deux:

Synchronisation à l'aide d'un sémaphore de comptage: Disons que vous avez 3 tâches - # 1 et 2 que vous voulez exécuter après 3. Comment concevriez-vous votre synchronisation?

thread t1{
...
s.P();
//block of code B1

thread t2{
...
s.P();
//block of code B2

thread t3{
...
//block of code B3
s.V();
s.V();
}

Donc, si votre sémaphore commence fermé, vous vous assurez que les blocs t1 et t2 soient ajoutés à la liste des sémaphores. Vient ensuite tout le t3 important, termine son activité et libère le t1 et le t2. Dans quel ordre sont-ils libérés? Dépend de l'implémentation de la liste des sémaphores. Pourrait être FIFO, pourrait être basé sur une priorité particulière, etc. (Note: réfléchissez à la façon dont vous organiseriez vos P et V; s si vous vouliez que t1 et t2 soient exécutés dans un ordre particulier, et si vous n'étiez pas au courant de l'implémentation du sémaphore)

(Découvrez: Que se passe-t-il si le nombre de V est supérieur au nombre de P?)

Exclusion mutuelle en utilisant des sémaphores de comptage: J'aimerais que vous construisiez votre propre pseudocode pour cela (vous fait mieux comprendre les choses!) - mais le concept fondamental est le suivant: un sémaphore de comptage de compteur = N permet N tâches pour entrer librement dans la section critique. Cela signifie que vous avez N tâches (ou threads, si vous le souhaitez) entrez dans la section critique, mais la tâche N + 1 est bloquée (va sur notre liste de tâches bloquées préférée), et n'est autorisée que lorsque quelqu'un V est le sémaphore au moins une fois. Ainsi, le compteur de sémaphores, au lieu de basculer entre 0 et 1, va maintenant entre 0 et N, permettant à N tâches d'entrer et de sortir librement, ne bloquant personne!

Maintenant, pourquoi auriez-vous besoin d'une serrure aussi bizarre? N'est-ce pas tout l'intérêt de l'exclusion mutuelle de ne pas laisser plus d'un mec accéder à une ressource ?? Pense. (Indice ... Vous n'avez pas toujours seulement n lecteur dans votre ordinateur, avez-vous ...?)

Réfléchir: L'exclusion mutuelle est-elle obtenue en ayant un sémaphore de comptage seul? Que se passe-t-il si vous avez 10 instances d'une ressource et que 10 threads entrent (via le sémaphore de comptage) et tentent d'utiliser la première instance?

8
aspen100

La différence la plus fondamentale entre le comptage et le sémaphore binaire est que:

  1. Sémaphore binaire ne peut pas gérer l'attente bornée car c'est juste une variable qui contient une valeur binaire. Compter le sémaphore Il peut gérer l'attente bornée car il a converti une variable en une structure avec une file d'attente.
  2. Implémentation de Strcuture sémaphore binaire: int s;

    Compter le sémaphore: Struct S {int s; Queue q; }

Utiliser le sémaphore de comptage maintenant, une fois gagné, le CS (Section critique) doit maintenant attendre que l'autre obtienne le CS, donc pas un seul processus. Chaque processus a une chance pour CS.

1
user7730503