会话计数器具有HttpSessionListener和会话计数变量访问权限

时间:2013-07-11 20:05:54

标签: java multithreading concurrency counter volatile

我在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提供请求的其他线程,是否可以使用精确值显示?

2 个答案:

答案 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,但是由于竞争条件读数,你可能仍会错过增量,然后并行增加计数器。