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();
}
}