Recientemente un amigo me hizo una pregunta (la que da título a esta entrada), yo pensaba que estaba clara para la mayoría de los programadores Java; pero pensando un poco al respecto, me di cuenta de que puede haber no pocas dudas al respecto. Y eso me ha llevado a escribir esta entrada en JavaHispano, con el fin de aclarar hasta donde yo pueda esta pregunta y con el deseo de que otros programadores de esta comunidad aporten su experiencia y conocimientos al respecto y que me ayuden a clarar los míos.
Para aquellos que hayan leído la documentación de Sun/Oracle, la pregunta puede parecer fácil de contestar. Citando esta fuente, podemos leer:
The Java Platform API Specification is a contract between callers and implementations.
The Specification describes all aspects of the behavior of each method on which a caller can rely. It does not describe implementation details, such as whether the method is native or synchronized. The specification should describe (textually) the thread-safety guarantees provided by a given object. In the absence of explicit indication to the contrary, all objects are assumed to be "thread-safe" (i.e., it is permissible for multiple threads to access them concurrently). It is recognized that current specifications don't always live up to this ideal.
Y por lo tanto, deduciremos que efectivamente, y encaso de que no se diga explícitamente lo contrario, las APIs oficiales de Java, son thread-safe. Es decir, podemos concluir que para las clases de los APIs oficiales, no es necesario incluir las llamadas a sus métodos dentro de un bloque synchronized.
Pues "yo no lo haría, foratesro". Se me ocurren al menos un par de argumentos en contra de esta primera intención:
a) ¿Qué pasa con los interfaces definidos por Sun/Oracle que son implementados por terceros (p.ej. DataSource)? ¿Podemos confiar en que han sido implementados de forma "thread-safe"? Yo no confiaría mucho en ello. De hecho, si alguien se toma la molestia de googlear buscando si el método DataSource::getConnection() es thred-safe, verá que no hay forma de saberlo; a mi al menos me ha sido imposible encontrar la respuesta. Hasta donde yo sé: lo era pero ya no, espera que es que Oracle dice que sí, pero el otro dice que depende, es que no es lo mismo si es una aplicación "stand alone" que si corre en un servidor de aplicaciones, pero no es lo mismo un servidor de aplicaciones que otro... Un lío considerable.
b) Esta razón es aún más peliaguda que la anterior. Del párrafo en inglés citado anteriormente, se puede concluir que efectivamente y en un mundo ideal, las APIs oficiales son "thread-safe". Pero la última frase del texto citado admite claramente que esto no siempre ocurre, y no estoy hablando de Swing, del que sabemos perfectamente cómo funciona a este respecto. Por lo que mucho me temo que en más de un caso, la implementación no es "thread-safe".
Por las dos razones anteriores, yo personalmente y salvo que tenga muy claro que una clase o un método de una clase es "thread-safe", siempre incluyo las llamadas a las instancias de los APIs oficiales en bloques synchronized.
Sin embargo, me gustaría saber qué experiencia tienen otros programadores y cómo actúan a este respecto. Invito a todo a aquél que le apetezca a compartirla con los demás dejando sus comentarios en esta "thread" (no me he podido resistir :-))