Un ReentrantLock n'est pas structuré , contrairement aux synchronized
constructions - c'est-à-dire que vous n'avez pas besoin d'utiliser une structure de bloc pour le verrouillage et pouvez même maintenir un verrou entre les méthodes. Un exemple:
private ReentrantLock lock;
public void foo() {
...
lock.lock();
...
}
public void bar() {
...
lock.unlock();
...
}
Un tel flux est impossible à représenter via un seul moniteur dans une synchronized
construction.
En plus de cela, ReentrantLock
prend en charge l' interrogation des verrous et les attentes de verrouillage interruptibles qui prennent en charge le délai d'attente . ReentrantLock
prend également en charge la politique d' équité configurable , permettant une planification plus flexible des threads.
Le constructeur de cette classe accepte un paramètre d' équité facultatif . Lorsqu'ils sont définis true
, en cas de conflit, les verrous favorisent l'octroi de l'accès au thread qui attend le plus longtemps. Sinon, ce verrou ne garantit aucun ordre d'accès particulier. Les programmes utilisant des verrous équitables accessibles par de nombreux threads peuvent afficher un débit global inférieur (c'est-à-dire qu'ils sont plus lents; souvent beaucoup plus lents) que ceux utilisant le paramètre par défaut, mais présentent des écarts de temps plus petits pour obtenir des verrous et garantir un manque de famine. Notez cependant que l'équité des verrous ne garantit pas l'équité de la programmation des threads. Ainsi, l'un des nombreux threads utilisant un verrou équitable peut l'obtenir plusieurs fois de suite tandis que d'autres threads actifs ne progressent pas et ne maintiennent pas actuellement le verrou. Notez également que letryLock
ne respecte pas le paramètre d'équité. Il réussira si le verrou est disponible même si d'autres threads sont en attente.
ReentrantLock
peut également être plus évolutif , offrant de bien meilleures performances en cas de conflit élevé. Vous pouvez en savoir plus à ce sujet ici .
Cette allégation a cependant été contestée; voir le commentaire suivant:
Dans le test de verrouillage réentrant, un nouveau verrou est créé à chaque fois, il n'y a donc pas de verrouillage exclusif et les données résultantes ne sont pas valides. En outre, le lien IBM n'offre aucun code source pour le benchmark sous-jacent, il est donc impossible de déterminer si le test a même été effectué correctement.
Quand faut-il utiliser ReentrantLock
s? Selon cet article de developerWorks ...
La réponse est assez simple - utilisez-la lorsque vous avez réellement besoin de quelque chose qu'elle ne fournit synchronized
pas, comme des attentes de verrouillage temporisées, des attentes de verrouillage interruptibles, des verrous non structurés, des variables de condition multiples ou une interrogation de verrouillage. ReentrantLock
présente également des avantages d'évolutivité, et vous devez l'utiliser si vous avez réellement une situation qui présente un conflit élevé, mais n'oubliez pas que la grande majorité des synchronized
blocs ne présentent pratiquement jamais de conflit, et encore moins un conflit élevé. Je conseillerais de développer avec la synchronisation jusqu'à ce que la synchronisation se révèle insuffisante, plutôt que de simplement supposer que "les performances seront meilleures" si vous utilisezReentrantLock
. N'oubliez pas que ce sont des outils avancés pour les utilisateurs avancés. (Et les utilisateurs vraiment avancés ont tendance à préférer les outils les plus simples qu'ils peuvent trouver jusqu'à ce qu'ils soient convaincus que les outils simples sont inadéquats.) Comme toujours, faites-le bien d'abord, puis demandez-vous si vous devez ou non le rendre plus rapide.