0

我在 Sun 的“Core Servlets and JavaServer Pages vol 2”中看到了一个带有会话计数器的示例。
计数器只是建立在使用/HttpSessionListener增加/减少会话计数的基础上:sessionCreatedsessionDestroyed

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

4

2 回答 2

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();
    }
}
于 2013-07-16T09:48:33.823 回答
1

Servlet 3.0 的规范说(§ 11.5):

侦听器实例和线程

[...]

容器不需要将生成的通知同步到属性侦听器类。维护状态的侦听器类负责数据的完整性,并应明确处理这种情况。

所以不,代码不安全。使用 AtomicCounter 或同步对计数器的访问可以修复它。

使其 volatile 不会使其更安全,因为 ++ 不是原子操作。因此,由于 volatile,每个其他线程都会看到新值,但您可能仍然会由于竞争条件读取而错过增量,然后并行递增计数器。

于 2013-07-15T14:56:17.967 回答