会话计数器具有HttpSessionListener和会话计数变量访问权限
我在Sun的“Core Servlets和JavaServer Pages vol 2”中看到了一个带会话计数器的例子。
Counter简单地构建在HttpSessionListener
并使用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.
监听器在上下文中注册自己,因此servlets
可以访问它并获得计数器值。
没有同步块。
是否安全, currentSessionCount
volatile
?
currentSessionCount
可以缓存在CPU寄存器中,并且对于使用servlets
提供请求的其他线程的精确值是不可见的?
Servlet 3.0的规范说(§11.5):
监听器实例和线程
[…]
容器不需要将生成的通知同步到属性侦听器类。 维护状态的监听器类负责数据的完整性,并应明确处理此情况。
所以不,代码不安全。 使用AtomicCounter或同步对计数器的访问权限可以修复它。
使它变得不稳定并不会使它更安全,因为++不是primefaces操作。 所以每个其他线程都会看到新值,这要归功于volatile,但是由于竞争条件读取,你可能仍会错过增量,然后并行递增计数器。
这样会很安全。
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(); } }