¿Largo primitivo o atómico para un mostrador?
-
20-09-2019 - |
Pregunta
Tengo la necesidad de un contador de tipo long
Con los siguientes requisitos/hechos:
- El incremento del mostrador debe tomar el menor tiempo posible.
- El mostrador solo será escrito por un hilo.
- La lectura del mostrador se realizará en otro hilo.
- El mostrador se incrementará regularmente (hasta unos pocos miles de veces por segundo), pero solo se lee una vez cada cinco segundos.
- La precisión precisa no es esencial, solo una idea aproximada del tamaño del mostrador es lo suficientemente buena.
- El mostrador nunca se desprende, disminuye.
Según estos requisitos, ¿cómo elegiría implementar su contador? Como un simple long
, como un volatile long
o usar un AtomicLong
? ¿Por qué?
Por el momento tengo un volatile long
Pero me preguntaba si otro enfoque sería mejor. También estoy incrementando mi largo al hacer ++counter
Opuesto a counter++
. ¿Es esto realmente más eficiente (como me han hecho creer en otro lugar) porque no se está haciendo una tarea?
Solución
Dados estos conjuntos de requisitos, yo pensar que una volatile
largo debería ser suficiente. El mostrador no sería incorrecto con un novolatile
largo, pero el lector podría estar leyendo información rancia en ese caso.
Un problema es que lee y escribe a un long
son no requerido ser atómico, por el Especificación JVM Si no se declara volatile
. Eso significaría que el hilo de lectura podría obtener un valor prácticamente ficticio si lee el valor, mientras que el hilo de escritura ha actualizado una parte del valor, pero no la otra.
La diferencia entre ++counter
y counter++
es probablemente Irrelevante, ya que el JVM se dará cuenta de que el valor de la expresión ya no se usa y los dos son equivalentes en este caso.
Otros consejos
En Java 8, use longadder que sea incluso mejor que el atomiclong donde la contención de hilos es alta.
Longadder Javadoc:
Esta clase generalmente es preferible a AtomicLong cuando múltiples hilos actualizan una suma común que se usa para fines como la recolección de estadísticas, no para el control de sincronización de grano fino. Bajo una 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.
¿Cuál es el requisito de tiempo de actividad para su programa? ¿Podrías conformarte con un int-volátiles int y las lecturas picantes?
10^4 incrementos / el segundo es 1 cada 100 USEC. La eficiencia no es un problema, pero la atomicidad podría ser. Es posible que tenga 2 copias, y cuando se lea, si no son iguales, lea nuevamente.
Este artículo Habla sobre las posibles formas de implementar un contador, creo que esta implementació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;
}
}