Est-ce que Java Regex Thread Safe?

J’ai une fonction qui utilise Pattern#comstack et un Matcher pour rechercher une liste de chaînes pour un motif.

Cette fonction est utilisée dans plusieurs threads. Chaque thread aura un modèle unique transmis au Pattern#comstack lorsque le thread est créé. Le nombre de threads et de patterns est dynamic, ce qui signifie que je peux append plus de Pattern et de threads lors de la configuration.

Dois-je synchronize cette fonction si elle utilise une expression régulière? Regex dans le thread Java est-il sûr?

Oui , à partir de la documentation de l’API Java pour la classe Pattern

Les instances de cette classe (Pattern) sont immuables et peuvent être utilisées par plusieurs threads simultanés. Les instances de la classe Matcher ne sont pas sûres pour une telle utilisation.

Si vous examinez le code centré sur les performances, essayez de réinitialiser l’instance Matcher à l’aide de la méthode reset () au lieu de créer de nouvelles instances. Cela réinitialiserait l’état de l’instance Matcher, la rendant utilisable pour la prochaine opération de regex. En fait, c’est l’état maintenu dans l’instance Matcher qui est responsable de son access simultané.

Sécurité des threads avec des expressions régulières en Java

RÉSUMÉ:

L’API d’expression régulière Java a été conçue pour permettre le partage d’un modèle unique compilé entre plusieurs opérations de correspondance.

Vous pouvez appeler en toute sécurité Pattern.matcher () sur le même modèle à partir de différents threads et utiliser en toute sécurité les matchers simultanément. Pattern.matcher () est sûr pour construire des matchers sans synchronisation. Bien que la méthode ne soit pas synchronisée, interne à la classe Pattern, une variable volatile appelée compilé est toujours définie après la construction d’un modèle et lue au début de l’appel à matcher (). Cela force tout thread faisant référence au Pattern à “voir” correctement le contenu de cet object.

D’autre part, vous ne devriez pas partager un Matcher entre différents threads. Ou du moins, si vous l’avez déjà fait, vous devriez utiliser une synchronisation explicite.

Même si vous devez vous rappeler que la sécurité des threads doit également prendre en compte le code environnant, vous semblez avoir de la chance. Le fait que les Matchers soient créés à l’aide de la méthode de fabrique de masortingces du Pattern et que les constructeurs ne soient pas des constructeurs publics est un signe positif. De même, vous utilisez la méthode statique de compilation pour créer le modèle englobant.

Donc, en bref, si vous faites quelque chose comme l’exemple:

 Pattern p = Pattern.comstack("a*b"); Matcher m = p.matcher("aaaaab"); boolean b = m.matches(); 

tu devrais bien te débrouiller.

Suivi de l’exemple de code pour plus de clarté: notez que cet exemple implique fortement que le Matcher ainsi créé est un thread-local avec le Pattern et le test. Par exemple, vous ne devez pas exposer le Matcher ainsi créé à d’autres threads.

Franchement, c’est le risque de toute question de sécurité des threads. La réalité est que tout code peut être rendu dangereux pour les threads si vous essayez suffisamment. Heureusement, il existe des livres merveilleux qui nous apprennent tout un tas de façons de détruire notre code. Si nous évitons ces erreurs, nous réduisons considérablement notre propre probabilité de problèmes de threading.

Un coup d’œil au code de Matcher.java montre un tas de variables membres, y compris le texte en cours de correspondance, des tableaux pour les groupes, quelques index pour la localisation de la maintenance et quelques boolean pour les autres états. Tout cela pointe vers un Matcher à états qui ne se comporterait pas bien s’il était accédé par plusieurs Threads . Ainsi le JavaDoc :

Les instances de cette classe ne peuvent pas être utilisées par plusieurs threads simultanés.

Ce n’est un problème que si, comme le fait remarquer @Bob Cross, vous faites tout votre possible pour autoriser l’utilisation de votre Matcher dans des Thread distincts. Si vous devez le faire et que vous pensez que la synchronisation posera problème pour votre code, vous pouvez utiliser un object de stockage ThreadLocal pour gérer un Matcher par thread de travail.

Pour résumer, vous pouvez réutiliser (conserver dans les variables statiques) les Pattern (s) compilés et leur dire de vous donner de nouveaux Matchers lorsque cela est nécessaire pour valider ces modèles de regex contre une chaîne de caractères.

 import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Validation helpers */ public final class Validators { private static final Ssortingng EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$"; private static Pattern email_pattern; static { email_pattern = Pattern.comstack(EMAIL_PATTERN); } /** * Check if e-mail is valid */ public static boolean isValidEmail(Ssortingng email) { Matcher matcher = email_pattern.matcher(email); return matcher.matches(); } } 

voir http://zoomicon.wordpress.com/2012/06/01/validating-e-mails-using-regular-expressions-in-java/ (vers la fin) concernant le modèle RegEx utilisé ci-dessus pour valider les e-mails ( dans le cas où il ne correspond pas aux besoins de validation du courrier électronique tel que publié ici)