2009-11-04 11 views
21

Soy realmente nuevo en Java y he leído que "sincronizado" es "muy caro" en Java. Todo lo que quiero saber es qué es caro y cómo es caro. Gracias.¿Por qué son costosas las sincronizaciones en Java?

+16

¡Oh muchacho! Eso abrirá una lata de gusanos. Ni siquiera quiero comenzar ... –

Respuesta

29

Maybe it's not as bad as you think

lo que solía ser terrible (que es, posiblemente, por qué se lee que era "muy caro"). Estos memes pueden tomar mucho tiempo para morir

Here es un buen artículo sobre el tema

¿Qué tan caro es la sincronización?

Debido a las reglas que implican el lavado de caché e invalidación, un bloque sincronizado en el lenguaje Java es generalmente más caros que las instalaciones sección crítica que ofrece muchas plataformas, que se implementan normalmente con un atómica "prueba y establecer el bit" instrucción de máquina . Incluso cuando un programa contiene solo un hilo que se ejecuta en un solo procesador, una llamada a un método sincronizado es aún más lenta que una llamada a un método no sincronizado. Si la sincronización realmente requiere contender por el bloqueo, la penalización de rendimiento es sustancialmente mayor, ya que habrá varios conmutadores de subprocesos y se requerirán llamadas al sistema.

Afortunadamente, las mejoras continuas en la JVM han mejorado el rendimiento general del programa Java y reducido el costo relativo de la sincronización con cada versión, y se prevén mejoras futuras. Además, a menudo se exageran los costos de rendimiento de la sincronización. Una fuente bien conocida ha citado que una llamada a un método sincronizado es hasta 50 veces más lenta que una llamada a un método no sincronizado. Si bien esta afirmación puede ser cierta, también es bastante engañosa y ha llevado a muchos desarrolladores a evitar la sincronización, incluso en los casos en que se necesita.

Habiendo dicho eso, la programación simultánea puede ser lenta, pero no tanto es solo culpa de Java ahora. Existe una compensación entre el bloqueo fino y grueso. Demasiado grueso es obviamente malo, pero también es posible que sea demasiado fino, ya que los bloqueos tienen un costo no nulo.

Es importante tener en cuenta el recurso particular en cuestión. Los discos duros mecánicos son un ejemplo donde más hilos pueden llevar a peor rendimiento.

+0

¿Hay un artículo más nuevo ahora? Parece que Java 1.4 no se lanzó en el momento de este artículo. Dado que esta publicación se encuentra en los tres primeros lugares de Google para el rendimiento de sincronización, las personas pueden tener una idea equivocada al leer este artículo anterior. Gracias. – Teddy

+0

@Teddy, esta pregunta y respuesta son realmente acerca de qué sincronización fue particularmente lenta en las versiones anteriores de Java. Ahora los problemas con el rendimiento concurrente son los mismos que en cualquier otro idioma. Los hilos simplemente no son la bala mágica que algunas personas desean que sean. –

11

Es costoso porque si está utilizando subprocesos, y varios subprocesos tienen que pasar por una sección sincronizada de código, solo uno de ellos se puede ejecutar a la vez.

Es como un cuello de botella.

Incluso es costoso cuando utiliza un solo hilo, ya que tiene que comprobar de todos modos si se le permite ejecutar.

Si se reduce el uso de segmentos sincronizado el hilo no tendrá que parar para ver si se puede ejecutar (por supuesto, no tienen que compartir datos)

Una visión general de alto nivel de cómo la sincronización las obras se pueden encontrar here

http://img20.imageshack.us/img20/2066/monitor28synchronizatioc.png

monitor de estilo Java

+0

Imagen hacia abajo ..... – Pacerier

5

Este article más en IBM realidad resume muy bien los principales puntos detrás de la sincronización.

Debido a las reglas que implican el lavado de caché e invalidación, un bloque sincronizado en el lenguaje Java es generalmente más caros que las instalaciones sección crítica que ofrece muchas plataformas, que se implementan normalmente con un atómica "prueba y establecer el bit" instrucción de la máquina. Incluso cuando un programa contiene solo un hilo que se ejecuta en un solo procesador, una llamada a un método sincronizado es aún más lenta que una llamada a un método no sincronizado. Si la sincronización realmente requiere contender por el bloqueo, la penalización de rendimiento es sustancialmente mayor, ya que habrá varios conmutadores de subprocesos y se requerirán llamadas al sistema.

+16

Tenga en cuenta que la versión más reciente de Java que el artículo cita es Java 1.3. Esa versión fue lanzada en mayo de 2000 y desde hace mucho tiempo ha sido EOLed. Si bien los hechos básicos siguen siendo algo similares (el modelo de memoria de Java modificó parte de él), ha habido toneladas de optimizaciones que hacen que la sincronización sea muy barata en el caso no comprobado, por ejemplo. –

+0

s/no comprobado/sin oposición/obviamente. –

+3

Y, por supuesto, tanto la exclusión mutua de bloques de código como la coherencia de la memoria son fundamentalmente necesarios al escribir código multiproceso, y no hay trucos "inteligentes" (solo sutiles) en Java para evitarlos. Si tus dos hilos tienen que interactuar, tienes que sincronizar: puro y simple. La sincronización de granularidad es la única pregunta restante. –

5

Esto no es tan específico de Java. La sincronización puede considerarse "costosa" en cualquier entorno de subprocesos múltiples si no se realiza correctamente. Si es particularmente malo en Java, no lo sé.

Impide que los subprocesos se ejecuten al mismo tiempo si utilizan el mismo recurso. Pero, dado que hacen usan el mismo recurso, no hay mejor opción (tiene que hacerse).

El problema es que las personas suelen proteger un recurso con un alcance demasiado grande. Por ejemplo, un programa mal diseñado puede sincronizar una matriz completa de objetos en lugar de cada elemento individual en la matriz (o incluso una sección de la matriz).

Esto significa que un hilo que intente leer el elemento 7 debe esperar la lectura de un hilo o escribir el elemento 22. No es necesario. Si la granularidad de la sincronización estuviera en el nivel del elemento en lugar del nivel de la matriz, esos dos hilos no interferirían entre sí.

Solo cuando dos subprocesos intentaron acceder al elemento mismo, habría contención de recursos. Es por eso que la regla general es proteger solo un recurso tan pequeño como sea posible (sujeto a limitaciones en el número de sincronizaciones, por supuesto).

Pero, para ser honesto, no importa lo caro que es si la alternativa es la corrupción de datos debido a dos hilos peleando por un único recurso. Escriba su aplicación correctamente y solo preocúpese por los problemas de rendimiento si y cuando aparecen ("Haz que funcione primero luego hazlo funcionar rápido" es mi mantra favorito).

2

Las otras respuestas dan un buen nivel de detalles técnicos que no intentaré replicar.

Lo que voy a hacer es aconsejarle que compruebe las fechas de los artículos (así como la competencia implícita y la conciencia del autor). La sincronización en Java fue muy lenta en las JVM anteriores.Sin embargo, ha mejorado mucho recientemente, de modo que la sincronización no prevista es mucho más rápida de lo que podría pensar, y la sincronización no controlada también ha mejorado.

Tenga en cuenta que esta pregunta posiblemente no importe, si necesita sincronizar para garantizar la corrección, necesita para sincronizarse y garantizar la corrección. Las únicas veces que puedo ver que la velocidad es un problema es si estaba considerando crear una implementación sin bloqueo en su lugar (utilizando el muy eficiente aunque complejo java.util.concurrent.locks.AbstractQueuedSynchronizer), o quizás considerando usar otro idioma para su tarea.

En general, creo que la mejor conclusión es que la sincronización es generalmente lo suficientemente rápida como para usarla en una primera iteración. Al igual que con todas las preocupaciones sobre el rendimiento, primero codifique la claridad y la corrección y luego solo optimice lo que mide para que sea una parte costosa de su aplicación. Por lo general, este no será el costo de la sincronización *.

Cuestiones relacionadas