发生高并发时的java Servlet问题
这是一个姐妹问题,与我之前的帖子相关: Simple web server when high-concurrency is met
面试问题是:
public class CounterServlet extends HttpServlet{
private volatile static int counter=0;
public int getCounter()
{
return counter;
}
public void service(HttpServletRequest request
HttpServletResponse response) throws IOException
{
counter++;
PrintWriter out=response.getWriter();
out.write("hello");
}
当遇到高并发性时,上面的代码会有什么问题? 我的分析是:Servlet是单例的,因此在同步中会出现问题。它已将计数器声明为易失性,这不会阻止问题的发生。我建议同步服务方法
# 1 楼答案
为此,您应该使用AtomicInteger。但是,因为只有一个Servlet实例存在,它被重用用于来自多个客户机的多个请求。因此,不要在Servlet中声明任何实例或类变量,也不要使方法同步。如果您想使用primitive
int
,可以执行如下操作# 2 楼答案
如果您通过多个线程访问静态值,则每个线程都可以拥有其本地缓存副本!为了避免这种情况,可以将变量声明为
static volatile
,这将强制线程每次读取全局值。然而,volatile并不能代替正确的同步您需要同步代码,尽管您只是在计数器上执行增量操作,但这并不意味着整个方法将是原子的。可能有多个线程使用寄存器中的当前值同时递增。这可能会导致不良结果
您需要
synchronize
该方法或使用AtomicInteger
进行这样一个简单的操作# 3 楼答案
因为volatile只是告诉编译器不要优化这个变量,所以它不会帮助解决与并发性相关的问题
我不知道您将如何处理
counter
,因为您只是在递增它,但我们可以确定,在调用service
方法N次之后,计数器将不等于N为了防止这种情况发生,可以使方法同步(我认为这不是正确的方法),同步某个锁对象上的递增部分,或者(我认为这是最合适的方法)使用AtomicInteger而不是int-AtomicInteger类确保对象上的所有操作都是以原子方式完成的