我在Sun的“Core Servlets和JavaServer Pages vol 2”中看到了一个带会话计数器的例子
计数器只是构建在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
提供请求的其他线程,是否可以使用精确值显示?
答案 0 :(得分:5)
这是安全的。
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();
}
}
答案 1 :(得分:1)
Servlet 3.0规范说(§11.5):
监听器实例和线程
[...]
容器不需要同步生成的通知 属性监听器类。维护状态的监听器类负责 数据的完整性,应该明确处理这种情况。
所以不,代码不安全。使用AtomicCounter或同步对计数器的访问可以修复它。
使它变得不稳定并不会使它更安全,因为++不是原子操作。所以每个其他线程都会看到新值,这要归功于volatile,但是由于竞争条件读数,你可能仍会错过增量,然后并行增加计数器。