Es Java Regex Thread Safe?

Tengo una función que usa la Pattern#compile y un Matcher para buscar una lista de cadenas para un patrón.

Esta función se usa en múltiples hilos. Cada hilo tendrá un patrón único que se pasará a la Pattern#compile cuando se cree el hilo. La cantidad de hilos y patrones son dynamics, lo que significa que puedo agregar más Pattern e hilos durante la configuración.

¿Debo synchronize esta función si usa expresiones regulares? ¿Es segura la expresión regular en el hilo de Java?

, de la documentación de la API de Java para la clase Pattern

Las instancias de esta clase (Patrón) son inmutables y son seguras para su uso por múltiples hilos concurrentes. Las instancias de la clase Matcher no son seguras para tal uso.

Si está buscando un código centrado en el rendimiento, intente restablecer la instancia de Matcher utilizando el método reset (), en lugar de crear instancias nuevas. Esto restablecería el estado de la instancia de Matcher, haciéndolo utilizable para la próxima operación de expresión regular. De hecho, es el estado mantenido en la instancia de Matcher el responsable de que no sea seguro para el acceso simultáneo.

Seguridad de subprocesos con expresiones regulares en Java

RESUMEN:

La API de expresión regular de Java se ha diseñado para permitir que un patrón comstackdo individual se comparta en varias operaciones de coincidencia.

Puede llamar de forma segura a Pattern.matcher () en el mismo patrón desde diferentes subprocesos y usar las correspondencias de manera segura al mismo tiempo. Pattern.matcher () es seguro para construir emparejamientos sin sincronización. Aunque el método no está sincronizado, es interno a la clase Pattern, una variable volátil llamada compiled se establece siempre después de construir un patrón y leer al inicio de la llamada a matcher (). Esto fuerza a cualquier hilo que se refiera al Patrón a “ver” correctamente el contenido de ese objeto.

Por otro lado, no debe compartir un Matcher entre diferentes hilos. O al menos, si alguna vez lo hizo, debe usar la sincronización explícita.

Si bien debes recordar que la seguridad del hilo también debe tener en cuenta el código que lo rodea, parece que estás de suerte. El hecho de que Matchers se haya creado utilizando el método de fábrica de emparejadores de Pattern y carezca de constructores públicos es una señal positiva. Del mismo modo, utiliza el método estático de comstackción para crear el Patrón abarcador.

Entonces, en resumen, si haces algo como el ejemplo:

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

deberías estar haciendo bastante bien.

Seguimiento del ejemplo del código para mayor claridad: tenga en cuenta que este ejemplo implica fuertemente que el Matcher así creado es thread-local con el Patrón y la prueba. Es decir, no debe exponer el Matcher así creado a ningún otro hilo.

Francamente, ese es el riesgo de cualquier pregunta sobre seguridad de hilos. La realidad es que cualquier código puede hacerse inseguro si se esfuerza lo suficiente. Afortunadamente, hay libros maravillosos que nos enseñan un montón de maneras en que podemos arruinar nuestro código. Si nos mantenemos alejados de esos errores, reducimos en gran medida nuestra propia probabilidad de problemas.

Una mirada rápida al código de Matcher.java muestra un grupo de variables miembro que incluye el texto que se está emparejando, matrices para grupos, algunos índices para mantener la ubicación y algunos boolean para otro estado. Todo esto apunta a un Matcher estado que no se comportaría bien si se accede por múltiples Threads . Lo mismo ocurre con JavaDoc :

Las instancias de esta clase no son seguras para su uso por múltiples hilos concurrentes.

Esto es solo un problema si, como @Bob Cross señala, usted hace todo lo posible para permitir el uso de su Matcher en Matcher separados. Si necesita hacer esto, y cree que la sincronización será un problema para su código, una opción que tiene es usar un objeto de almacenamiento ThreadLocal para mantener un Matcher por hilo de trabajo.

Para resumir, puede reutilizar (mantener variables estáticas) los patrones comstackdos y decirles que le den Matchers nuevos cuando sea necesario para validar esos patrones de expresiones regexáneas contra alguna cadena.

 import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Validation helpers */ public final class Validators { private static final String 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.compile(EMAIL_PATTERN); } /** * Check if e-mail is valid */ public static boolean isValidEmail(String email) { Matcher matcher = email_pattern.matcher(email); return matcher.matches(); } } 

ver http://zoomicon.wordpress.com/2012/06/01/validating-e-mails-using-regular-expressions-in-java/ (cerca del final) con respecto al patrón RegEx utilizado anteriormente para validar los correos electrónicos ( en caso de que no se ajuste a las necesidades de validación de correo electrónico tal como se publica aquí)