2010-03-15 14 views
17

que tienen una necesidad de un contador del tipo long con los siguientes requisitos/hechos:Long primitive o AtomicLong for a counter?

  • incrementar el contador debe tomar tan poco tiempo como sea posible.
  • El contador solo se escribirá con un hilo.
  • La lectura del contador se realizará en otro hilo.
  • El contador se incrementará regularmente (tanto como unos miles de veces por segundo), pero solo se leerá una vez cada cinco segundos.
  • La precisión precisa no es esencial, solo una idea aproximada del tamaño del contador es suficiente.
  • El contador nunca se borra, disminuye.

En función de estos requisitos, ¿cómo elegiría implementar su contador? ¿Como simple long, como volatile long o usando AtomicLong? ¿Por qué?

Por el momento tengo un volatile long pero me preguntaba si otro enfoque sería mejor. También estoy incrementando mi tiempo haciendo ++counter en comparación con counter++. ¿Es esto realmente más eficiente (como me han hecho creer en otro lado) porque no se está haciendo una tarea?

Gracias de antemano

Rich

+0

volátil debe estar bien, ya que el contrato establece que cada lectura en una variable volátil se produce después de la liberación de bloqueo de una escritura anterior. – fasseg

+0

Si solo lo actualizas unas mil veces por segundo y usas un procesador no incorporado, la diferencia es irrelevante; puede hacer millones de actualizaciones de 'AtomicLong' por segundo en la mayoría de las máquinas en estos días. Aún así, estoy de acuerdo en que 'volátil' debería ser suficiente. Podrías codificar los dos a la vez y comprobar con qué frecuencia coinciden (y cuándo no lo hacen) si querías estar seguro. –

+0

@Riduidel estamos contando los paquetes de datos entrantes, y realmente no nos importa si el número es 12,345,678 o si es un poco tarde a 12,345,602 – Rich

Respuesta

11

Dadas estas series de requisitos, que piensan que un volatile tiempo debería ser suficiente. El contador no sería incorrecto con una longitud no volatile, pero el lector podría estar leyendo información obsoleta en ese caso.

Un problema es que lee y escribe a un long son not required to be atomic, por el JVM specification si no se declara volatile. Eso significaría que el hilo de lectura podría obtener un valor bastante ficticio si lee el valor, mientras que el hilo de escritura ha actualizado una parte del valor, pero no el otro.

La diferencia entre ++counter y counter++ es probablemente irrelevante, ya que la JVM se dará cuenta de que el valor de la expresión no se utiliza más y los dos son equivalentes en este caso.

0

¿Cuál es el requisito de tiempo de actividad para su programa? ¿Podrían arreglárselas con un int no volátil y lecturas picantes?

+0

El tiempo de actividad es el mayor tiempo posible, esto se está ejecutando dentro de un servidor. – Rich

0

10^4 incrementos/segundo es 1 cada 100 usec. La eficiencia no es un problema, pero la atomicidad podría serlo. Puede tener 2 copias y cuando se leen, si no son iguales, vuelva a leer.

0

Este article habla de las posibles maneras de implementar un contador de Creo que esta aplicación debería funcionar para usted

class LessNaiveVolatieIdGenerator { 
private static volatile long id = 0; 
public static long nextId() { 
    long nextId = (id = id + 1); // or nextId = id++; 
    return nextId; 
} 

}

4

En Java 8, utiliza LongAdder que es incluso mejor que AtomicLong donde el hilo la contención es alta.

LongAdder JavaDoc:

Esta clase es generalmente preferible AtomicLong cuando varios subprocesos actualizar una suma común que se utiliza para fines tales como la recogida de estadísticas, no para el control de la sincronización de grano fino. Bajo baja contención de actualización, las dos clases tienen características similares. Pero bajo una alta contención, el rendimiento esperado de esta clase es significativamente mayor, a expensas de un mayor consumo de espacio.

+0

La contención no es alta. Solo un hilo estará escribiendo en él. –