即使不涉及“检查并执行”操作,也可能发生竞争条件,例如,在以下代码中,十个请求将导致十个线程,但此后计数器不保证为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++;
}
我只是想知道是否有另一种处理这种情况的方法?
由于
答案 0 :(得分:3)
答案 1 :(得分:1)
正如 pajton 建议的那样,使用AtomicInteger
或AtomicLong
,incrementAndGet()
方法会更好。
没有synchronized
的代码不仅是竞争条件的主题,还引入了线程可见性问题。请参阅volatile
关键字。
答案 2 :(得分:0)
++在技术上是一个3个操作“get-and-set”: 1)检索当前值 2)将值加1 3)存储新值
线程上下文切换可以出现在这3个步骤中的任何位置,导致每个线程在任何给定的时间点看到diff值。
正如其他人所指出的那样,这是Atomics的完美候选者。这是关于这个主题的一个很好的链接:http://www.javamex.com/tutorials/synchronization_concurrency_7_atomic_updaters.shtml
使计数器变量不稳定在这里是不够的,因为新值取决于旧值,因此受上下文切换引起的竞争条件的影响。这是另一个很好的链接:http://www.ibm.com/developerworks/java/library/j-jtp06197.html
这是一个非常常见的面试问题,顺便说一句......