Je lis le livre Java Concurrence dans la pratique. Dans une section sur La mise en œuvre n'a pas d'objets de permis réels et Quelqu'un peut-il expliquer cela? J'ai du mal à comprendre cela. Si nous créons un pool de taille fixe, nous créons un nombre fixe de "permis". De la déclaration ci-dessus, on dirait que les "permis" peuvent continuer à grandir. Pourquoi est-il conçu de cette façon? P> java.util.concurrent.semaphore code>, les lignes ci-dessous sont présentes dans le livre. C'est un commentaire sur sa mise en œuvre des objets "Permis virtuels" P>
sémaphore code> fait
ne pas associer les permis dispensés avec des threads, donc un permis acquis dans
Un thread peut être libéré d'un autre fil. Vous pouvez penser à
acquérir code> comme consommant un permis et
libérer code> comme en créant un; une
Semaphore Code> ne se limite pas au nombre de permis qu'il a été créé avec. P>
blockQuote>
6 Réponses :
Quelqu'un peut-il expliquer cela? De la déclaration ci-dessus, on dirait que les "permis" peuvent continuer à grandir. p> blockQuote>
Un sémaphore est un compteur de permis. Acquérir est comme la décrément qui attend plutôt que d'aller sous zéro. Il n'a pas de limite supérieure. P>
Pourquoi est-il conçu de cette façon? P> blockQuote>
parce que c'est simple à le faire. P>
Aucune limite supérieure, la limite supérieure ne serait-elle pas le nombre de permis?
La limite supérieure est le nombre de fois que la libération des temps moins le nombre de fois acquis a été appelée. Vous pouvez appeler la sortie n'importe quel nombre de fois. Il y a une limite supérieure d'integer.max_value dans certaines implémentations.
Alors, comment va-t-on créer un sémaphore solide avec un maximum de 1 - quel que soit l'appel à la libération de fois?
@slott pour que je voudrais utiliser un atomicboolant. Vous pouvez SET (TRUE) CODE> Pour publier et
CaqueAreAreSet (True, False) Code> Pour acquérir. Ceci est non bloqué.
Est-ce trop exclu pour prolonger le sémaphore et la libération de remplacement pour faire des drainages ()?
Au lieu de "distribuer" des objets de permis, la mise en œuvre a juste un compteur. Lorsqu'un nouveau permis est "créé", le compteur est augmenté, lorsqu'un permis est "retourné", le compteur est diminué. P>
Cela permet de mieux performer que de créer des objets réels tout le temps. P>
Le compromis est que le sémaphore lui-même ne peut pas détecter certains types d'erreurs de programmation (telles que des encaissements de permis non autorisés, ou des fuites de sémaphore). En tant que codeur, vous devez vous assurer de suivre les règles vous-même. P>
Java fournit-il un type de sémaphore différent qui applique en réalité la limite de permis? Je veux juste que la libération () soit un non-op lorsque tous les permis ont déjà été libérés ... dans un système complexe avec beaucoup de threads, il n'est pas si facile de vous assurer que chaque thread acquiert et libère exactement un permis .
@DAssurant: Je suppose que vous pourriez rouler le vôtre au-dessus d'Atomicinteger. Mais cela ne ressemble pas à une bonne approche. Vous devez vraiment vous assurer que votre code de verrouillage est logiquement correct. Si vous trouvez la nécessité de faire publier un non-OP, cela signifie probablement que quelqu'un publie plus de serrures que ce qu'ils n'auraient dû le faire. Et cela brisera des choses qui ne peuvent pas être corrigées en ignorant simplement certains appels de sémaphore.
Vous pouvez également utiliser le mode de verrouillage traditionnel «synchronisé». Moins flexible, mais sûr (aucune fuite, prend soin de la réintensif, etc.).
Je pense que cela signifie que cela signifie que ce que nous pouvons avoir besoin de sémaphore comme les moments où nous avons publié "extra" et plus les permis qu'il a créés.
tel que: p>
Je suis confondu par cela longtemps; et a l'air fou cela est autorisé
Peut-être la dernière ligne "Un sémaphore ne se limite pas au nombre de permis qu'il a été créé avec" est votre source de confusion. p>
Un sémaphore lors de la création est initialisé avec un ensemble de permis fixes. Cela devient alors le nombre maximum de permis que le sémaphore peut simultanément se passer à tout moment pendant la durée de vie de ce sémaphore. Vous ne peut pas em> augmenter de manière dynamique ce nombre, sauf en réinitialisant le sémaphore. P>
Le sens Si la ligne citée (de JCIP) est la suivante: Premièrement, la sémantique de la manière dont un sémaphore fonctionne ne se limite pas aux détails de la délivrance et de la reprise d'un permis - cela se manifeste dans le fait que tout fil peut-il Accès au sémaphore peut avoir un permis publié (même si ce fil ne possédait pas le permis de la première place) P>
Deuxièmement, vous pouvez réduire de manière dynamique les permis maximaux d'un sémaphore - en appelant VaporMits (int) code> méthode. p>
Comme mentionné dans le premier message " Semaphore ne se limite pas au nombre de permis qu'il a été créé avec em>" p>
Chaque appel à .Release () API augmentera le nombre de permis par un. Donc, les sémaphores n'ont pas de taille de permis fixe p>
Pouvez-vous expliquer le travail .Release () alors? Donc, si je crée un objet de sémaphore avec 0, aucun thread ne peut acquérir le permis de celui-ci? Mais si j'appelle d'abord .Release () d'abord () .acquire () dans la ligne suivante, cela permettra à un fil d'acquérir un permis?
Il est surprenant à certains d'entre nous.
Vous pouvez facilement sous-classer un sémaphore délimitée. P>
/** * Terrible performance bounded semaphore. **/ public class BoundedSemaphore extends Semaphore { private static final long serialVersionUID = -570124236163243243L; final int bound; public BoundedSemaphore(int permits) { super(permits); bound=permits; } @Override synchronized public void acquire() throws InterruptedException { super.acquire(); } @Override synchronized public boolean tryAcquire() { return super.tryAcquire(); } @Override synchronized public void release() { if( availablePermits()<bound){ super.release(); } } @Override synchronized public void acquire(int count) throws InterruptedException { super.acquire(count); } @Override synchronized public boolean tryAcquire(int count) { return super.tryAcquire(count); } @Override synchronized public void release(int count) { if( availablePermits()<bound){ super.release(bound-availablePermits()); } } }
ressemble à une phrase ornée