while variable total hacer ejemplos definicion contadores contador como ciclo acumuladores acumulador java multithreading concurrency counter volatile

java - total - Contador de sesión con HttpSessionListener y acceso variable de conteo de sesión



total-=-- contador java (2)

Vi un ejemplo con el contador de sesiones en "Servlets principales y JavaServer Pages vol 2" de Sun.
Counter simplemente se basa en HttpSessionListener y aumenta / disminuye el número de sesiones con sessionCreated / sessionDestroyed :

public class SessionCounter implements HttpSessionListener { private int currentSessionCount = 0; public void sessionCreated(HttpSessionEvent event) { currentSessionCount++; } ... public int getTotalSessionCount() { return(totalSessionCount); } ... // counter decrement, self registering in context attribute etc.

El oyente se registra en el contexto, por lo que los servlets pueden acceder a él y obtener el valor del contador.
No hay un bloque sincronizado.
¿Es seguro que currentSessionCount no sea volatile ?

¿Puede currentSessionCount almacenarse en caché en el registro de la CPU y no ser visible con el valor exacto para otros subprocesos que sirven la solicitud con servlets ?


La especificación de Servlet 3.0 dice (§ 11.5):

Instancias de Escucha y Roscado

[...]

El contenedor no es necesario para sincronizar las notificaciones resultantes para atribuir clases de escucha. Las clases de escucha que mantienen el estado son responsables de la integridad de los datos y deben manejar este caso de manera explícita.

Entonces, no, el código no es seguro. Usar un AtomicCounter o sincronizar el acceso al contador lo corrige.

Hacerlo volátil no lo hace más seguro, porque ++ no es una operación atómica. Por lo tanto, cada otro subproceso verá el nuevo valor gracias a la volatilidad, pero es posible que aún pierda incrementos debido a una lectura de condición de carrera, y luego incremente el contador en paralelo.


Esto sería seguro.

public class HttpSessionListenerTest implements HttpSessionListener { final private AtomicInteger sessionCount = new AtomicInteger(0); @Override public void sessionCreated(HttpSessionEvent event) { sessionCount.incrementAndGet(); } @Override public void sessionDestroyed(HttpSessionEvent event) { sessionCount.decrementAndGet(); } public int getTotalSessionCount() { return sessionCount.get(); } }