【问题标题】:Hit Counter Servlet命中计数器 Servlet
【发布时间】:2011-03-26 17:02:01
【问题描述】:

即使不涉及“检查并执行”操作,也可能发生争用情况,例如,在以下代码中,十个请求将导致十个线程,但此后计数器不保证为 10。首先我说的对吗?

private int numPageHits;   
public void doGet(HttpServletRequest request, 
                                 HttpServletResponse response) 
                                       throws IOException, ServletException 
    { 
       //this method executes whenever the servlet is hit 
       //increment numPageHits 
       numPageHits++; 
    }

一种解决方案是使用同步块,例如:

synchronize(this) {
    numPageHits++; 
}

我只是想知道是否有其他方法可以处理这种情况?

谢谢

【问题讨论】:

    标签: servlets thread-safety


    【解决方案1】:

    【讨论】:

      【解决方案2】:

      按照pajton的建议,使用AtomicIntegerAtomicLongincrementAndGet()方法会更好。

      没有synchronized的代码不仅是竞争条件的主题,而且还引入了线程可见性问题。见volatile关键字。

      【讨论】:

        【解决方案3】:

        你是对的。 ++ 不是原子操作(即使它看起来是),因此受到 JVM/Java 内存模型的重新排序优化和线程上下文切换的影响。

        ++ 在技术上是一个 3 操作“get-and-set”: 1) 检索当前值 2) 将值加 1 3) 存储新值

        线程上下文切换可以发生在这 3 个步骤中的任何位置,导致每个线程在任何给定时间点看到差异值。

        正如其他人所指出的,这是 Atomics 的完美候选者。这是关于这个主题的一个很好的链接:http://www.javamex.com/tutorials/synchronization_concurrency_7_atomic_updaters.shtml

        在这里使计数器变量 volatile 是不够的,因为新值取决于旧值,因此会受到上下文切换引起的竞争条件的影响。这是另一个很好的链接:http://www.ibm.com/developerworks/java/library/j-jtp06197.html

        这是一个很常见的面试问题,顺便说一句...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-01-22
          • 2016-02-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-28
          • 1970-01-01
          相关资源
          最近更新 更多