2011-05-21 91 views
4

我知道這是一個簡單的問題,但我有點困惑。Servlet doGet同步 - 不起作用?

如果我理解得很好,用簡單的話來說,當請求到達Web服務器時,他會爲每個請求創建一個線程給某個servlet。

考慮,我們在MyServlet下一個代碼(我離開了異常處理和類似):

synchronized protected void doGet(... ...){ 
    PrintWritet pw=response.getWriter(); 
    String param=request.getParameter("p"); 

    if(param.equals("a")){ 
     wait(); 
    }else{ 
     notifyAll(); 
    } 

    pw.write("Hello!"); 
} 

我希望這個servlet將卡住了,因爲第一個線程(用PARAM =一)進入該方法將永遠等待,因爲任何其他未來線程都會因爲同步關鍵字而停留在doGet前面,並且因爲notifyAll永遠不會被執行。如果我在瀏覽器中打開新標籤並點擊/ MyServlet?p = a,瀏覽器正在等待127.0.0.1 ... 然後,我打開新標籤並點擊/ MyServlet?p = b(或任何其他任何東西即!= a)釋放第一個標籤並打印出「Hello!」信息。

這意味着第二個線程已經進入doGet,並執行了notifyAll。

這是怎麼發生的?我錯過了什麼?

回答

8

由於wait()通過輸入​​塊來釋放之前獲得的鎖定。從的Javadoc Object.wait

這款顯示器並等待另一個線程的線程釋放所有權線程通知等候在這個對象監視器上或者通過notify方法或notifyAll方法的調用醒來。該線程然後等待,直到它可以重新獲得監視器的所有權並恢復執行。

因此,您的第一個請求獲取鎖,輸入doGet方法,並調用wait(它釋放鎖和等待)。第二個請求獲得鎖,輸入doGet,並調用notifyAll,喚醒第一個請求的線程。

這是您在之前仔細閱讀像waitnotify/notifyAll的方法的文檔,你使用它們,否則你會惹上麻煩關鍵

+0

非常感謝您的回答 – slomir 2011-05-22 01:04:22