Hit Counter Servlet
Race condition could occur even when "check-and-act" action is not involved, for example in the following code ten requests would result in ten threads but the counter is not guaranteed to be 10 after that. First of all am I right in saying that?
private int numPageHits;
public void doGet(HttpServletRequest request,
开发者_StackOverflow HttpServletResponse response)
throws IOException, ServletException
{
//this method executes whenever the servlet is hit
//increment numPageHits
numPageHits++;
}
One solution could be to use synchronize block like:
synchronize(this) {
numPageHits++;
}
I was just wondering if there is another way of handling this situation?
Thanks
Use AtomicInteger and its method AtomicInteger.addAndGet()
As pajton suggested, use AtomicInteger
or AtomicLong
, incrementAndGet()
method would be even better.
The code without synchronized
is not only a subject of race condition, but also introduces thread visibility problem. See volatile
keyword.
you are correct. ++ is not an atomic operation (even though it looks like it is) and therefore subject to reordering optimizations and thread context switches by the JVM/Java Memory Model.
++ is technically a 3 operation "get-and-set": 1) retrieve the current value 2) add 1 to the value 3) store the new value
thread context switches can occur anywhere in those 3 steps causing each thread to see diff values at any given point in time.
this is a perfect candidate for Atomics, as others have pointed out. here's a good link on this topic: http://www.javamex.com/tutorials/synchronization_concurrency_7_atomic_updaters.shtml
making the counter variable volatile is not enough here as the new value depends on the old and therefore subject to race conditions caused by the context switching. here's another good link: http://www.ibm.com/developerworks/java/library/j-jtp06197.html
this is a very common interview question, btw...
精彩评论