IT程序员开发必备-各类资源下载清单,史上最全IT资源,个人收藏总结!
问题:首先哪些情况会出现线程安全问题呢?、
(1)对于实例变量(非静态的全局变量),如果是多个实例对象,则线程安全;如果是单实例,则线程不安全!如:
Servlet.java
public class ServletDemo1 extends HttpServlet {
int i = 0;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
i++;
try {
Thread.sleep(1000*5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
PrintWriter out = response.getWriter();
out.print("This is the doGet method of the ServletDemo1,i = "+i);
}
由于HttpServlet是单实例,只会被实例化一次,即多个请求共享同一个Servlet,如果Servlet还没有被实例化,则当两个用户同时访问该Servlet(相隔1秒)时,第一个用户打印"i=2",第二个用户也打印"i=2",这里的原因能想明白吧。
解决办法:
public class ServletDemo1 extends HttpServlet {
int i = 0;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
synchronized (this) {
try {
i++;
Thread.sleep(1000*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
PrintWriter out = response.getWriter();
out.print("This is the doGet method of the ServletDemo1,i = "+i);
}
}
}
(2)对于类变量(静态变量),即使是实例化多个对象,其类变量也是供所有实例对象所共享,所以线程不安全!如:
Person.java
public class Person {
public static int age;
}
Servlet.java
public class ServletDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Person person = new Person();
person.age++;
try {
Thread.sleep(1000*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
PrintWriter out = response.getWriter();
out.print("This is the doGet method of the ServletDemo1,person.age = "+person.age);
}
由于HttpServlet是单实例,只会被实例化一次,即多个请求共享同一个Servlet,如果Servlet还没有被实例化,则当两个用户同时访问该Servlet(相隔1秒)时,第一个用户打印"person.age=2",第二个用户也打印"person.age=2",这里的原因能想明白吧。因为虽然每个请求都会new Person(),然后将age++;他们虽然是两个不同的实例对象,但是age是属于Person类而不属于某一个实例,所以两个对象操作的是同一个age,所以线程不安全,
解决办法:
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Person person = null;
synchronized (this) {
try {
person = new Person();
person.age++;
Thread.sleep(1000*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
PrintWriter out = response.getWriter();
out.print("This is the doGet method of the ServletDemo1,person.age = "+person.age);
}
}