Servlet 本質多線程,主代碼路徑(service/doGet/doPost)嚴禁同步,否則退化為單線程,吞吐量劇降。若不可避免需保護共享狀態,請使用 專用鎖對象 並 將同步塊縮小至最小必要範圍。
public class BadServlet extends HttpServlet {
private int numberOfRows = 0;
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
synchronized (this) { // 鎖住整個 Servlet 實例!
int startingRows = numberOfRows;
// 資料庫操作、業務邏輯... 全在鎖內
}
}
}
後果:併發請求排隊,CPU 閒置,響應時間隨並發線性增長。
public class GoodServlet extends HttpServlet {
private int numberOfRows = 0;
private final Object lockObject = new Object(); // 專用鎖
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
int startingRows;
synchronized (lockObject) { // 僅保護讀取共享變量
startingRows = numberOfRows;
}
// 資料庫操作、耗時邏輯在鎖外並發執行
Connection conn = ds.getConnection(...);
// ...
}
}

圖示:同步主路徑(紅線)隨並發用戶數響應時間指數級上升;細粒度鎖(藍線)近似線性增長。
ConcurrentHashMap、AtomicInteger 等無鎖結構。