我有一个servlet代码,用于维护访问它的次数。
在doGet方法的某一点上,在访问该部分的次数上进行增量的点。
任何人都可以详细说明为什么要这样做以及如果在doGet方法中没有完成同步会产生什么影响。
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
public class FirstAccessed extends HttpServlet{
private Date first;
private int count;
public void init() throws ServletException {
// Enter the time/date when the server calls this servlet and
// initialize counter
first = new Date();
count = 0;
return;
}
public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType("text/plain");
PrintWriter out = res.getWriter();
int local_count;
synchronized(this) {
local_count = ++count;
}
out.println("<HTML>");
out.println("<HEAD><TITLE>First Accessed Servlet</TITLE></HEAD>");
out.println("<BODY>");
out.println("This servlet was first loaded by the server at " + first);
out.println("<br>The current time is " + new Date());
out.println("<br>");
out.println("This servlet has been accessed " + local_count + " times.");
out.println("</BODY></HTML>");
}
}
答案 0 :(得分:4)
++
不是原子操作。它涉及
count
,count
。 如果此块未同步,则并行执行doGet()
方法的两个线程可能会进入竞争状态。例如,两个线程可能
而不是从(例如)8到10,它将从8变为9,缺少一个增量。
同步也是必要的,以确保一个线程所做的count
的更改对之后读取其值的所有其他线程可见。如果没有同步,您也会有丢失增量的风险。
请注意,虽然您不在代码中的任何位置创建和执行线程,但Web容器本身会创建并执行它们。因此,如果您的应用的两个用户同时点击同一个链接,他们各自的请求将由两个不同的线程处理,两个线程同时调用您的servlet的doGet()
方法。