By default JSP is not thread safe. Let us see why JSP is thread unsafe and how to make it thread-safe. One of the difference between instance and local variable is local variables are thread safe where as instance variables in a class are not thread safe. The same thing is applied to JSP page also. There is an interview question “Are JSPs thread safe by default? “. By default, JSP engine assumes that JSPs are thread-safe because the default <%@ page isThreadSafe=”true”%> directive tells the JSP engine that a JavaServer Page is thread-safe. So multiple threads are allowed to execute a JSP at the same time. But , the JSPs are not thread-safe by default because “instance variables declared in a JSP are not thread safe “. To understand this in detail , Let us see how JSPs are working and how instance variables are declared in JSP?.
One of the reason is to use JSP over servlet is that coding a JSP page is more convenient than coding the equivalent servlet. But JSP pages are working just like servlets. When a JSP is first requested by an user, the JSP translator translates the page (.jsp page) into servlet class (.java file) and is compiled by java compiler. Then the Servlet engine creates one instance of the servlet class and runs the the same object. Each time a new request comes in, a new thread is created and invokes the service() method of the object (JSP page). So only one instance of the JSP page is instantiated and all user requests are therefore handled by a single object. As multiple threads are accessing the same object, the code must be thread safe.
Now let us see how variables are declared in JSP? Variables are declared using the following forms of scripting elements
1. Using JSP declaration element (<%! Java Code %>) -To define methods and instance variables that get inserted into the main body of the servlet class (outside of the _jspService method).
2. Using Scriptlet element (<% Java Code %>) -To insert java code ( including declaration of local variables ) into the servlet’s _jspService method.
Variable declared using a JSP declaration are inserted into the body of the generated servlet class, outside of any existing methods and becomes instance variables. Variables declared using Scriptlet element goes as a local variables into the _jspService method of the generated servlet class. As we know , instance variables are thread unsafe where as local variables are thread safe. Let us see how it is applicable to JSP ?
Thread issues with instance variable:
The variables declared using JSP declaration leads your page to threading issues. In general, an instance variable declared in a class retains its value when the method run by a thread returns. It is shared across all the threads executing code of the same instance. If one thread changes the value of the instance variable, the new value is visible to all threads. The same thing is applied to JSP page also. If the variables declared in a JSP declaration block (instance variable) are changed when one user accesses the page, all other users accessing the same page will get the new value.
For example, the following simple code in JSP is not thread safe:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
//using jsp declaration
<%!int pageno=0;%>
//using scriptlets
<% pageno=Integer.parseInt(request.getParameter("startPageNo"));
for (int i=1;i<=100;i++)
{ %>
< P >S.No: <%=i%>P >
<% if (i%20==0)
{ %>
< P >Page Number : <%=pageno>P >
<%
pageno=pageno+1; }
}
%>
|
In the above code pageno is an instance variable which is shared between threads. When the above page is called by two users at the same time , when the first thread executes the for loop, the second thread may intialize the page number to new value before the first thread completes the for loop. Now the first thread gets the new value of pageno. This would lead to complete failure of the JSP.
Fixing with local variable :
When you declare a variable within a scriptlet element instead of in a JSP declaration block, the variable becomes a local variable in the generated servlet’s _jspService method. As each thread has its own copy of a local variable in the stack frame, it does not lead to any threading issues ,even if more than one thread executes the same code at the same time. Also If the value of a local variable is changed by one thread, it will not affect the other threads. The above code is replaced with local variable pageno instead of instance variable to fix the thread issues.
<% int pageno=Integer.parseInt(request.getParameter(“startPageNo”));
for (int i=1;i<=100;i++)
…
…
%>
To solve threading issues in JSP:
1. You can implement the SingleThreadModel interface. This is done in JSP by adding the below directive to your jsp page
<%@ page isThreadSafe=”false” %> that tells the JSP engine that a JSP is not thread-safe
When you implement SingleThreadModel interface, jsp engine creates new instance of that jsp page for each user request. But implementing SingleThreadModel interface leads to some performance issue that may be suitable for low traffic sites. So it is better to avoid this if possible. Even if the isThreadSafe attribute is false , we must ensure that accesses to any shared objects using the ServletContext or the HttpSession are properly synchronized.
2. You can use synchronized block or synchronized method
Another approach to thread safety is to keep the few lines of code (Only shared data area) inside synchronized block or to declare any method inside JSP declartion as synchronized.
For example , the following block of code are synchronized .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
<% synchronized ( this )
{
pageno=Integer.parseInt(request.getParameter( "startPageNo" ));
for ( int i= 1 ;i<= 100 ;i++)
{ %>
S.No: <%=i%>
<% if (i% 20 == 0 )
{ %>
Page Number : <%=pageno%>
<%pageno=pageno+ 1 ;
}
}
}
%>
|
Although synchronization can prevent threading problems, we need to pay the cost of performance.
In the above code , to avoid synchronization and to fix the thread issues we can declare pageno as local variable instead of instance variable.
1. Avoid to declare variables using JSP declaration (<%! %> tags) and local variables may be used to fix threading issues.
2. Take care of the objects you store in the application / servletcontext and session (httpSession) objects. For example, javabeans stored in the application scope are not at all thread safe because it is shared with other JSPs in the context. Java beans created in the session scope are thread safe as each browser has its own session. But threading issues for objects stored in the session may occur , if a user has two windows open from the same browser or the user clicks on a link or button twice. Ensure that any access to shared objects using application or session are properly synchronized or make sure that the object itself is internally thread-safe.
3. Avoid to use any libraries which are thread unsafe or use with proper synchronization.
4. No need to worry about Page and Request level attributes , because they are thread safe
5. The JspWriter class (the out implicit object) is properly synchronized.