2009-06-10 9 views
11

He estado debatiéndome esto durante los últimos minutos, y veo razones para sí y no. Esto se derivó de mirar las respuestas al Java HashMap vs. Hashtable y ver a varias personas decir que Hashtable es de hecho más lento.¿Son los métodos sincronizados más lentos en aplicaciones con un solo subproceso?

Me parece que un método sincronizado debe actuar absolutamente igual que su contraparte no sincronizada si se ejecuta en un solo hilo, ya que la acción de sincronización no debe bloquear nada. Dicho esto, me imagino que el compilador maneja los dos casos de manera diferente y es por eso que la gente dice que sincronizar es más lento.

No

que es de ninguna manera concluyentes, pero me encontré con algunas pruebas sencillas en HashMap vs Hashtable, y vio poca diferencia en la velocidad.

+1

El cuello de botella estaría en su algoritmo. Por lo tanto, la sobrecarga de sincronización debe ser menor. – sybreon

Respuesta

15

Sí, los programas Java de una sola punta que usan la sincronización pueden ser ligeramente más lentos de lo que estarían sin sincronización. Para versiones anteriores de Java, la sincronización era costosa. Para cualquier versión moderna, sin embargo, la sincronización no atendida es bastante barata. No me preocuparía por esto.

Tenga en cuenta que Java 6 tiene y Java 7 es tener buenas optimizaciones alrededor de bloqueo:

  • bloqueo engrosamiento
  • bloqueo elisión
  • vuelta adaptativa bloqueo
  • sesgada bloqueo

Para obtener más información, consulte el Java SE 6 Performance White Paper. También tenga en cuenta que la sincronización no prevista parece ser más costosa en CPU multinúcleo que en CPU de un solo núcleo, quizás debido a los requisitos de sincronización del modelo de memoria de Java que obligan a las memorias caché locales a compartirse con otras CPU o alguna otra barrera de memoria. Por ejemplo, lea Do Java 6 threading optimizations actually work? - Part II. (La Parte I no fue tan perspicaz como la Parte II.)

+0

+1 por mencionar contención: la sincronización en sí es barata. – serg10

+0

@ serg10: ¿Contención? En un solo programa de subprocesos? Nop. –

5

Sí. Van a ser un poco más lentos debido a la sobrecarga adicional de mantener las cerraduras.

+3

apenas tan levemente. +1 – sybreon

+0

... SI el JIT no puede decidir que no necesita mantener los bloqueos en este caso ... –

0

Al usar estructuras de datos sincronizadas, la ralentización no depende de "cuánto" se bloquea. El acto de adquirir o liberar un bloqueo es lento, ya que generalmente implica algo así como una llamada al sistema (los conmutadores de contexto son lentos en cualquier plataforma). En un entorno JIT como una JVM típica, sería teóricamente posible optimizar todas las llamadas de bloqueo/desbloqueo cuando solo hay un hilo en ejecución, pero debería invalidarse correctamente cada vez que se inicie otro hilo.

Tenga en cuenta que cosas como futexes de Linux no tienen que hacer llamadas al sistema a menos que haya contención, pero su uso es aún más lento que un no-op.

+0

excepto si el sistema operativo es intercambiable en caliente de la CPU, supongo; entonces la JVM no podría hacer esa suposición? –

+0

El problema no es tanto si hay varias CPU como si hay múltiples subprocesos dentro de la JVM. Es cierto que saber si hay varias CPU ampliará la aplicabilidad de esta optimización, pero es mucho más común ejecutar una única aplicación con subprocesos cuando hay varias CPU. El punto que estaba tratando de transmitir es que no conozco ninguna analogía mutex con excepciones de costo cero. – user57368

+0

Si lo * solo * que su código estaba haciendo era adquirir y liberar bloqueos, sí, sería lento. Siempre que los bloqueos sean lo suficientemente bajos, cualquier desaceleración en el código sería mínima, especialmente cualquier JVM reciente. El bloqueo desatendido ya no es costoso. – Eddie

Cuestiones relacionadas