Pregunta Java multihilo y publicación segura


Despues de leer "Java concurrente en la práctica"y"OSGI en la práctica"Encontré un tema específico muy interesante: publicación segura. Lo siguiente es de JCIP:

Para publicar un objeto de forma segura, tanto la referencia al objeto como el estado del objeto deben hacerse visibles para otros hilos al mismo tiempo. Un objeto correctamente construido puede ser publicado de manera segura por:

  • Inicializando una referencia de objeto de una estático inicializador.
  • Almacenar una referencia en un volátil campo.
  • Almacenar una referencia en un final campo.
  • Almacenar una referencia a ella en un campo que está debidamente protegido por un (sincronizado) bloqueo.

Mi primera pregunta: ¿cuántos desarrolladores de Java están al tanto de esto (problema)? ¿Cuántas aplicaciones de Java en el mundo real realmente están siguiendo esto? ¿Y esto es realmente un problema real? Tengo la sensación de que el 99% de las JVM implementadas no son tan "malas", es decir, un hilo no está garantizado (de hecho es práctico (casi) "imposible") para ver datos obsoletos solo porque la referencia no está siguiendo el "idioma de publicación segura" arriba.


32
2018-04-29 11:49


origen


Respuestas:


Proporcionalmente, es probable que sea justo decir que muy pocos programadores comprenden suficientemente la sincronización y la concurrencia. Quién sabe cuántas aplicaciones de servidor hay en la actualidad administrando transacciones financieras, registros médicos, registros policiales, telefonía, etc., que están llenos de errores de sincronización y funcionan esencialmente por accidente, o fallan muy ocasionalmente (nunca se supo que alguien tenga un fantasma). ¿Llamada telefónica agregada a su factura de teléfono?) por razones que nunca se analizan o llegan al fondo de.

La publicación de objetos es un problema particular porque a menudo se pasa por alto, y es un lugar donde es bastante razonable que los compiladores realicen optimizaciones que podrían provocar un comportamiento inesperado si no lo conocen: en el código compilado JIT, almacenando un puntero, luego, incrementarlo y almacenar los datos es algo muy razonable de hacer. Podrías pensar que es "malo", pero en un nivel bajo, es realmente como esperas que sea la especificación de JVM. (Por cierto, he oído que los programas de la vida real que se ejecutan en JRockit sufren este problema, no es puramente teórico).

Si sabe que su aplicación tiene errores de sincronización pero no se está comportando mal en su JVM actual en su hardware actual, entonces (a) felicidades; y (b), ahora es el momento de comenzar a "caminar con calma hacia la salida de emergencia", corregir el código y educar a los programadores antes de tener que actualizar demasiados componentes.


19
2018-04-29 15:21



"¿Es esto realmente un problema real?"

Si, absolutamente. Incluso la aplicación web más trivial tiene que enfrentar problemas relacionados con la concurrencia. A los servlets se accede por múltiples hilos, por ejemplo.

El otro problema es que el enhebrado y la concurrencia son muy difíciles de manejar correctamente. Es casi demasiado difícil. Es por eso que estamos viendo surgir tendencias como la memoria transaccional, y lenguajes como Clojure que con suerte hacen que la concurrencia sea más fácil de manejar. Pero tenemos un camino por recorrer antes de que estos se conviertan en la corriente principal. Por lo tanto, tenemos que hacer lo mejor con lo que tenemos. Leer JCiP es un muy buen comienzo.


4
2018-04-29 16:14



En primer lugar, la "publicación segura" no es realmente una expresión idiomática (OMI). Viene directamente del lenguaje.

Ha habido casos de problemas con la publicación insegura, con el uso de NIO, por ejemplo.

La mayoría del código de Java está muy mal escrito. El código enhebrado es obviamente más difícil que el código de línea de negocio promedio.


2
2018-04-29 11:58



No es una cuestión de ser "malvado". Eso es un problema real, y será mucho más evidente con el aumento de las arquitecturas multinúcleo en los próximos años. He visto errores de producción muy reales debido a la sincronización incorrecta. Y para responder a su otra pregunta, diría que muy pocos programadores son conscientes del problema, incluso entre desarrolladores "buenos".


2
2018-04-29 13:32



Diría que muy pocos programadores están lejos de este problema. ¿Cuándo fue el último ejemplo de código que ha visto que utilizó la palabra clave volátil? Sin embargo, la mayoría de los otros condicionados mencionados, simplemente los dediqué como mejores prácticas.

Si un desarrollador desatiende por completo esas condiciones, rápidamente encontrará errores de subprocesamiento múltiple.


1
2018-04-29 12:04



Mi experiencia (corto plazo y consultoría en muchos tipos diferentes de entornos La mayoría de las aplicaciones que he visto) están de acuerdo con esta intuición. Nunca he visto un sistema completo claramente diseñado para gestionar este problema con cuidado (bueno, casi nunca he visto un sistema completo claramente estructurado). He trabajado con muy, muy pocos desarrolladores con un buen conocimiento de problemas de enhebrado.

Especialmente con aplicaciones web, a menudo puede salirse con la suya, o al menos parece salirse con la suya. Si tiene instancias basadas en la primavera que administran la creación de objetos y los servlets sin estado, a menudo puede pretender que no existe la sincronización, y este es el tipo donde terminan muchas aplicaciones. Eventualmente, alguien comienza a poner un estado compartido donde no pertenece y 3 meses después alguien nota algunos errores intermitentes. Esto suele ser "lo suficientemente bueno" para muchas personas (siempre que no esté escribiendo transacciones bancarias).

¿Cuántos desarrolladores de Java conocen este problema? Es difícil de decir, ya que depende en gran medida del lugar donde trabajas.


1
2018-04-29 13:46