Question

Le sémaphore peut-il être inférieur à 0? Je veux dire, disons que j'ai un sémaphore avec N = 3 et que j'appelle "bas" 4 fois, alors N restera 0 mais un processus sera bloqué?

Et pareil, si au début j'appelle, est-ce que N peut être supérieur à 3? Parce que comme je le vois, si N peut être supérieur à 3 si au début j'appelle plusieurs fois, plus tard, je pourrais appeler plus de fois que je ne le peux, mettant ainsi plus de processus dans la section critique, le sémaphore me le permet. .

Si quelqu'un clarifiait un peu cela pour moi, j'apprécierais beaucoup.

Greg

Était-ce utile?

La solution

Appeler quand il est 0 ne devrait pas fonctionner. Appeler quand il est 3 ne fonctionne. (Je pense à Java).

Laissez-moi en ajouter un peu plus. Beaucoup de gens pensent que les verrous ressemblent à des sémaphores (binaires) (c'est-à-dire - N = 1, de sorte que la valeur du sémaphore est 0 (détenu) ou 1 (non détenu)). Mais ce n'est pas tout à fait correct. Un verrou a la notion de "propriété". il peut donc être "réentrant". Cela signifie qu'un thread qui détient un verrou est autorisé à appeler à nouveau lock () (ce qui déplace effectivement le nombre de 0 à -1), car le thread détient déjà le verrou et est autorisé à "rentrer" de nouveau. il. Les serrures peuvent également être non réentrantes. Un détenteur de verrou doit appeler unlock () le même nombre de fois que lock ().

Les sémaphores n’ont pas de notion de propriété et ne peuvent donc pas être réentrants, bien qu’il soit possible d’acquérir autant de permis que possible. Cela signifie qu'un thread doit bloquer lorsqu'il rencontre la valeur 0, jusqu'à ce que quelqu'un incrémente le sémaphore.

De plus, dans ce que j'ai vu (Java), vous pouvez incrémenter le sémaphore au-delà de N, ce qui concerne également la propriété: un sémaphore n'a aucune notion de propriété, donc tout le monde peut lui donner plus de permis. . Contrairement à un fil, où chaque fois qu'un thread appelle unlock () sans le verrouiller, c'est une erreur. (En Java, une exception sera lancée).

J'espère que cette façon de penser vous aidera.

Autres conseils

(Utilisation de la terminologie de java.util.concurrent.Semaphore à partir de la balise Java. Certaines de ces informations sont spécifiques à l'implémentation. Je suppose que votre "panne" est le du code du sémaphore Java acquis () méthode, et votre "up" est release () .)

Oui, votre dernier appel à acquérir () sera bloqué jusqu'à ce qu'un autre thread appelle release () ou votre thread soit interrompu.

Oui, vous pouvez appeler release () plus de fois, puis plusieurs fois de suite, au moins avec java.util.concurrent.Semaphore .

D'autres implémentations d'un sémaphore peuvent avoir une idée de "maximum". nombre de permis, et un appel à libérer au-delà de ce maximum échouerait. La classe Semaphore de Java permet une situation inverse, dans laquelle un sémaphore peut démarrer avec un nombre négatif d'autorisations et où tous les appels discover () échoueront jusqu'à ce qu'il y ait suffisamment de < code> release () appelle. Une fois que le nombre de permis est devenu non négatif, il ne redeviendra jamais négatif.

Bonjour, Greg, considérons l'exemple suivant:

public static void main(String [] args) throws InterruptedException {

        Semaphore available = new Semaphore(1, true);

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());
    }

Si vous voyez la sortie, vous obtiendrez ce qui suit:

Acquire : 0
Released : 1
Released : 2
Released : 3
Released : 4
Acquire : 3
Acquire : 2
Acquire : 1
Acquire : 0

Et attendez.

Donc, fondamentalement, le permis augmentera à chaque sortie et l’acquérir le diminuera jusqu’à 0. Une fois qu'il aura atteint 0, il attendra que la version soit appelée sur le même objet :)

Oui, une valeur négative signifie que des processus attendent que le sémaphore soit libéré. Une valeur positive signifie que vous pouvez appeler plusieurs fois avant que le sémaphore ne se bloque.

Vous pouvez penser à la valeur de cette manière: un nombre positif signifie qu’il ya autant de ressources disponibles. Une valeur négative signifie que de nombreuses entités ont besoin d'une ressource lorsque toutes les ressources sont prises en ce moment. Lorsque vous acquérez une ressource, vous décrémentez la valeur, lorsque vous la relâchez, vous augmentez la valeur. Si la valeur est toujours > = 0 après la décrémentation, vous obtenez la ressource, sinon votre entité est placée dans une file d'attente.

Une belle explication des sémaphores dans Wikipedia: http://en.wikipedia.org/wiki/Semaphore_(programming)

Voyez simplement N comme le compteur qui compte votre ressource limitée. Étant donné que vous ne pouvez pas avoir un nombre négatif de ressources, N reste > = 0. Si le nombre de vos ressources disponibles change, le nombre maximal N doit également être modifié. Je n’aimerais pas considérer bon style d’incrémenter n sans le décrémenter d’abord dans les autres cas.

Utilisation de java.util.concurrent.Semaphore avec les méthodes acquérir () et release () , je pense que les autorisations seront toujours > = 0 . Supposons que vous souhaitiez synchroniser les threads de manière à ce qu'un seul thread puisse être en boucle. Si sem est le type de Semaphore ayant la valeur initiale 1, cela ne fonctionnera pas pour plus de 2 threads.

while(true){            

    sem.wait(); // wait is acquire

    for(int i=0; i<=5; i++){

        try {
            Thread.sleep(250);
        }catch (InterruptedException e) {}

        System.out.println("Thread "+ threadname+ " " + i);

             }
    sem.signal(); // signal is release }

Cependant, vous pouvez implémenter la classe Semaphore à partir de Java et créer votre propre classe qui le permet.

package yourpackage;

import java.util.concurrent.Semaphore;

public class SemaphoreLayer {
public Semaphore s=null;
public String name;
private int val;

public SemaphoreLayer(int i){
    s=new Semaphore(i); val=i;
}

public void wait(){
 try {
     val--;
     s.acquire();

  } catch (InterruptedException e) {
    System.out.println("Error signal semaphorelayer");
}}

public void signal(){
    if(val<0){val++;}{
        s.release();
        val++;
    }
}

}

Maintenant, val peut être négatif. Cependant, je ne suis pas sûr que cela soit complètement sûr, car si nous avons le signal d'un thread et attendons de l'autre et qu'ils essayent val ++ et val - , cela peut être mal. (Les chances pour que cela soit très faible mais elles existent toujours, donc si vous codez et que vous devez être 100% sans erreur, je ne recommande pas d'utiliser ce code) En conclusion, c’est pourquoi il est préférable d’utiliser le concept de moniteur en java et le mot clé synchronisé.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top