servlet是单例的,即在web服务器中最多只存在servlet的一个实例,那么servlet就是线程不安全的。下面通过以下代码模拟买票过程:
package com.zjb.servlet; import java.io.IOException; import java.io.PrintWriter; import java.util.Date; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyServlet1 extends HttpServlet { private int ticket = 2; /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request * the request send by the client to the server * @param response * the response send by the server to the client * @throws ServletException * if an error occurred * @throws IOException * if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html"); PrintWriter out = response.getWriter(); // out.println("hello,I am the first Myeclipse servlet,the currentTime is " // + new Date().toString()); if(ticket>0){ System.out.println("恭喜你,买到票了"); try { Thread.sleep(10*1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } ticket--; }else{ System.out.println("對不起,已經沒有票了"); } out.close(); } /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to * post. * * @param request * the request send by the client to the server * @param response * the response send by the server to the client * @throws ServletException * if an error occurred * @throws IOException * if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
从上面代码可以看出,现在一共有2张票,即只有2个请求可以买到票,然而当从浏览器发出三次请求是却出现了下面的结果:
那么,这种由单例造成的线程不安全问题该如何解决呢?只要把操作共享资源(如ticket)的代码加同步锁即可:
synchronized (this) { if(ticket>0){ System.out.println("恭喜你,买到票了"); try { Thread.sleep(10*1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } ticket--; }else{ System.out.println("對不起,已經沒有票了"); } }
时间: 2024-10-30 01:50:52