这是一个与我之前的帖子相关的姐妹问题: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是单例的,因此在synchronization.It中会有问题,将计数器声明为易失性,这不会阻止该问题。我建议同步服务方法?
发布于 2013-05-15 16:48:15
如果你通过多个线程访问一个静态值,那么每个线程都可以拥有它的本地缓存副本!为了避免这种情况,您可以将变量声明为static volatile,这将强制线程每次读取全局值。然而,易失性并不能代替正确的同步!
您需要同步代码,尽管您只是在计数器上进行递增,但这并不意味着整个方法将是原子的。可能有多个线程使用来自寄存器的当前值同时递增它。这可能会导致不期望的结果。
对于这种微不足道的操作,您需要对该方法执行synchronize操作或使用AtomicInteger。
发布于 2013-05-15 16:42:15
因为volatile只是告诉编译器不要优化这个变量,所以它不会帮助解决与并发相关的问题。
我不知道您将如何处理counter,因为您只会递增它,但我们可以肯定,在N次调用service方法之后,计数器将不会等于N。
为了防止这种情况的发生,可以使方法同步(我认为这不是正确的方法),同步某个锁对象上的递增部分,或者(我认为这是最合适的方法)使用AtomicInteger而不是int - AtomicInteger类来确保对象上的所有操作都是自动完成的。
发布于 2013-05-15 16:43:56
您应该对该purpose.But使用AtomicInteger,因为该Servlet只存在一个实例,可供来自多个clients.Hence的多个请求重用。如果您想使用原语int,请不要在Servlet中声明任何实例或类变量,也不要使方法synchronized.You可以做如下所示的事情。
public void service(HttpServletRequest request
HttpServletResponse response) throws IOException
{
synchronized (CounterServlet.class) {
count++;
}
PrintWriter out=response.getWriter();
out.write("hello");
}https://stackoverflow.com/questions/16560339
复制相似问题