问题描述
我在Sun的Core Servlets和JavaServer Pages vol 2中看到一个会话计数器的示例。
计数器只是建立在 HttpSessionListener
/减少会话计数 sessionCreated
/ sessionDestroyed
:
I saw an example with session counter in Sun's "Core Servlets and JavaServer Pages vol 2".
Counter is simply build on HttpSessionListener
and increments/decrements session count with 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
?
Listener register itself in context, so servlets
can access it and get counter value.
There is no synchronized block.
Is it safe, that currentSessionCount
is not volatile
?
可以将 currentSessionCount
缓存在CPU寄存器中,并且对于使用服务请求的其他线程的确切值不可见
Can currentSessionCount
be cached in CPU register and not visible with exact value for other threads that serve request with servlets
?
推荐答案
Servlet 3.0的规范说(§11.5):
The specification of Servlet 3.0 says (§ 11.5):
[...]
容器不需要将生成的通知
同步到属性侦听器类。维护状态的监听器类负责
数据的完整性,并应该明确处理这种情况。
The container is not required to synchronize the resulting notifications to attribute listener classes. Listener classes that maintain state are responsible for the integrity of the data and should handle this case explicitly.
代码不安全。使用AtomicCounter或同步对计数器的访问会修复它。
So no, the code is not safe. Using an AtomicCounter or synchronizing the access to the counter fixes it.
让它变得不稳定,因为它不是一个原子操作。所以每隔一个线程就会看到新的值,这要归功于volatile,但是你可能会因为一个竞态条件读取而错过增量,然后并行增加计数器。
Making it volatile doean't make it safer, because ++ is not an atomic operation. So every other thread will see the new value thanks to volatile, but you might still miss increments due to a race condition reading, then incrementing the counter in parallel.
这篇关于会话计数器与HttpSessionListener和会话计数变量访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!