¿Debo siempre hacer que mi código java sea seguro para subprocesos, o por razones de rendimiento, hacerlo solo cuando sea necesario?

Si creo clases, que se usan en este momento solo en un solo hilo, ¿debería hacerlas seguras para los hilos, incluso si no las necesito en este momento? Podría suceder que más tarde use esta clase en varios subprocesos, y en ese momento podría obtener condiciones de carrera y podría tener dificultades para encontrarlas si no hice que la clase sea segura para los subprocesos en primer lugar. ¿O debería hacer que la clase no sea segura para subprocesos, para un mejor rendimiento? Pero la optimización prematura es malvada.

Preguntado de manera diferente: ¿Debería hacer que mis clases sean seguras para subprocesos si es necesario (si se usan en varios subprocesos, de lo contrario no) o debería optimizar este problema cuando sea necesario (si veo que la sincronización consume una parte importante del tiempo de procesamiento)?

Si elijo una de las dos formas, ¿existen métodos para reducir las desventajas? ¿O existe una tercera posibilidad, que debería usar?

EDITAR : Doy la razón por la que se me ocurrió esta pregunta. En nuestra empresa, hemos escrito una administración de usuarios muy simple que escribe los datos en archivos de propiedades. Lo utilicé en una aplicación web y después de trabajar un poco, obtuve errores extraños, que la administración de usuarios olvidó las propiedades de los usuarios (incluidos el nombre y la contraseña) y los roles. Eso fue muy molesto pero no siempre reproducible, así que creo que fue una condición de carrera. Como sincronicé todos los métodos de lectura y escritura desde / en el disco, el problema desapareció. Entonces pensé, que probablemente podría haberme evitado toda la molestia, si hubiéramos escrito la clase con sincronización en primer lugar.

EDITAR 2 : Al mirar los consejos de Pragmatic Programmer, vi el consejo # 41: Diseñar siempre para la concurrencia. Esto no dice que todo el código debe ser seguro para subprocesos, pero dice que el diseño debe tener en cuenta la concurrencia.

Respuesta 1

Comience desde los datos. Decide qué datos se comparten explícitamente y protégelos. Si es posible, encapsule el bloqueo con los datos. Utilice colecciones concurrentes preexistentes seguras para subprocesos.

Siempre que sea posible, use objetos inmutables. Haga que los atributos sean finales, establezca sus valores en los constructores. Si necesita "cambiar" los datos, considere devolver una nueva instancia. Los objetos inmutables no necesitan bloqueo.

Para los objetos que no están compartidos o confinados en subprocesos, no pierda tiempo haciéndolos seguros para subprocesos.

Documente las expectativas en el código. Las anotaciones JCIP son la mejor opción predefinida disponible.

Respuesta: 2

Solía ​​tratar de hacer que todo sea seguro para subprocesos; luego me di cuenta de que el significado mismo de "seguro para subprocesos" depende del uso. A menudo simplemente no se puede predecir que el uso y la persona que llama tiene que tomar la acción de todos modos para usarlo de una manera segura para los subprocesos.

En estos días escribo casi todo suponiendo un solo subproceso, y pongo el conocimiento de subprocesos en los pocos lugares seleccionados donde importa.

Dicho esto, también creo (cuando corresponde) tipos inmutables, que son naturalmente susceptibles a múltiples subprocesos, además de ser más fáciles de razonar en general.

Respuesta: 3

Siga el principio de "lo más simple posible, pero no más simple". En ausencia de un requisito, no debe hacerlos seguros para subprocesos. Hacerlo sería especulativo y probablemente innecesario. La programación segura para subprocesos agrega mucha más complejidad a sus clases y probablemente las hará menos productivas debido a las tareas de sincronización.

A menos que se indique explícitamente que un objeto es seguro para subprocesos, la expectativa es que no lo es.

Respuesta: 4

Solo como un comentario secundario: Sincronización! = Seguridad de subprocesos. Aun así, es posible que no modifique los datos simultáneamente, pero puede leerlos simultáneamente. Por lo tanto, tenga en cuenta el Modelo de memoria de Java, donde la sincronización significa hacer que los datos sean confiables y estén disponibles en todos los hilos, no solo protegiendo la modificación concurrente del mismo.

Y sí, en mi opinión, la seguridad de subprocesos debe incorporarse desde el principio y depende de la lógica de la aplicación si necesita manejar la concurrencia. Nunca asumas nada e incluso si tu prueba parece estar bien, las condiciones de carrera son perros dormidos.

Respuesta: 5

Debe saber absolutamente qué segmentos de su código serán multiproceso y cuáles no.

Sin poder concentrar el área de multiproceso en una sección pequeña y controlable, no tendrá éxito. Las partes de su aplicación que son multiproceso necesitan ser revisadas cuidadosamente, completamente analizadas, entendidas y adaptadas para un entorno multiproceso.

El resto no lo hace y, por lo tanto, hacerlo a prueba de hilos sería un desperdicio.

Por ejemplo, con la interfaz gráfica de usuario de swing, Sun simplemente decidió que nada de eso sería multihilo.

Ah, y si alguien usa sus clases, depende de ellos asegurarse de que si está en una sección roscada, que sea segura.

Sun inicialmente salió con colecciones seguras (solo). el problema es que threadsafe no puede hacerse inseguro (para fines de rendimiento). Así que ahora salieron con versiones no seguras con envoltorios para que sean seguras. Para la mayoría de los casos, los envoltorios son innecesarios, supongamos que, a menos que esté creando los subprocesos usted mismo, que su clase no tiene que ser segura para subprocesos, sino que LO DOCUMENTA en los javadocs.

Respuesta: 6

Aquí está mi enfoque personal:

  • Haga que los objetos y la estructura de datos sean inmutables siempre que pueda. Esa es una buena práctica en general, y es automáticamente segura para subprocesos. Problema resuelto.
  • Si tiene que hacer que un objeto sea mutable, normalmente no se molestará en tratar de hacer que el hilo sea seguro . El razonamiento para esto es simple: cuando tiene un estado mutable, entonces el bloqueo / control no puede ser manejado de manera segura por una sola clase. Incluso si sincroniza todos los métodos, esto no garantiza la seguridad del hilo. Y si agrega sincronización a un objeto que solo se usa en un contexto de subproceso único, entonces acaba de agregar una sobrecarga innecesaria. Por lo tanto, es mejor dejar que la persona que llama / usuario implemente el sistema de bloqueo que sea necesario.
  • Si proporciona una API pública de nivel superior, implemente el bloqueo necesario para que su hilo API sea seguro . Para una funcionalidad de nivel superior, la sobrecarga de seguridad de los subprocesos es bastante trivial, y sus usuarios definitivamente lo agradecerán. ¡Una API con una semántica de concurrencia complicada que los usuarios deben evitar no es una buena API!

Este enfoque me ha servido bien con el tiempo: es posible que deba hacer una excepción ocasional, pero en promedio es un muy buen lugar para comenzar.

Respuesta: 7

Si desea seguir lo que hizo Sun en la API de Java, puede echar un vistazo a las clases de recopilación. Muchas clases de colección comunes no son seguras para subprocesos, pero tienen contrapartidas seguras para subprocesos. Según Jon Skeet (ver comentarios), muchas de las clases de Java originalmente eran seguras para subprocesos, pero no beneficiaban a los desarrolladores, por lo que algunas clases ahora tienen dos versiones: una es segura para subprocesos y la otra no es segura para subprocesos.

Mi consejo es no hacer que el código sea seguro para subprocesos hasta que sea necesario, ya que hay algunos gastos generales relacionados con la seguridad de subprocesos. Supongo que esto cae en la misma categoría que la optimización: no lo haga antes de que tenga que hacerlo.

Respuesta: 8

Diseñe por separado las clases para usar desde múltiples hilos y documente otras para ser usadas desde un solo hilo.

Las de un solo hilo son mucho más fáciles de trabajar.

La separación de la lógica multiproceso ayuda a que la sincronización sea correcta.

Respuesta: 9

"Siempre" es una palabra muy peligrosa en el desarrollo de software ... opciones como esta son "siempre" situacionales.

Respuesta: 10

Para evitar las condiciones de carrera, bloquee solo un objeto: lea las descripciones de las condiciones de carrera tediosamente y descubrirá que los bloqueos cruzados (la condición de carrera es incorrecta: la carrera se detiene allí) siempre son una consecuencia de dos hilos que intentan bloquearse dos + objetos

Sincronice todos los métodos y realice pruebas: para cualquier aplicación del mundo real que realmente tenga que lidiar con los problemas, la sincronización tiene un bajo costo. Lo que no te dicen es que todo se bloquea en las tablas de punteros de 16 bits ... en ese momento estás uh, ...

Solo mantén tu currículum de hamburguesa actualizado.

Respuesta: 11

public static String template = "$ A $ B" public static void somemethod () {template.replaceAll (Matcher.quoteReplacement ("$") + "A", "A"); template.replaceAll (Matcher.quoteReplacement ("$" ...

Así que instalé Alfresco y tengo dos aplicaciones web / alfresco y / share. ¿Cuál es la diferencia y los propósitos de estas aplicaciones? ¿Puede una aplicación existir sin la otra?

Todavía soy nuevo en Java y me gustaría entender cadenas y matrices, así que tuve la idea de manipular elementos y colocarlos de acuerdo con mi objetivo. El objetivo es que habrá Array ...

Estoy aprendiendo Java y estoy haciendo programas simples para encontrar la temporada en la que se encuentra un mes, según algunos ejemplos de libros. Estas dos clases demuestran dos formas de probar un valor: if / else if instrucción, ...