Synchronizing on servlet instance variable
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10

Thread: Synchronizing on servlet instance variable

  1. #1
    Join Date
    Sep 2017
    Posts
    15

    Synchronizing on servlet instance variable

    I am having trouble making a servlet thread-safe using synchronization.

    I do know it's best to avoid instance (state) variables in servlets, but my college assignment calls strictly for this.

    My servlet has an instance variable, shared among any number of threads that run. I need to use synchronization such that modification of this variable is only allowed to one thread at a time. I then need to test the effects of synchronization employed by using a Thread.currentThread().sleep(10000) delay timer within the synchronized(){} block.

    - The instance variable is of type double, so a number.
    - I hence can't use it as monitor, as it's not an object.
    - I hence set up synchronization blocks around code lines that modify this variable.
    - The syntax I used for these synchronization blocks is as follows:

    Code:
    synchronized(this)
        {
        // Actions to perform with the instance variable.
        }
    I researched a lot about servlets in this regard. My findings are the following:

    - using the "this" word as synchronization object does not work, because "this" is its own "this" for each thread of the servlet running. So if 4 users have simultaneously the servlet open in their browsers and are using it, that means there are 4 instances of the servlet running and using "this", each instance simply refers back to itself -> meaning it is as if there is no synchronization condition anyway. For synchronization to work, all instances must lock on one single variable.
    - Another finding states that there is always only one instance of a servlet running, and the multiple simultaneous users means multiple threads. But there is only one instance of the servlet.

    This is conflicting information.

    Please help: what should I do, how should I code, to synchronize operations using this instance variable, such that each next user (thread) must wait for the first thread to release the lock, before it can perform the operation???

    There were suggestions as follows:

    1) Construct a new object -> Object lock = new Object();
    2) Use synchronization on the desired instance variable, using the object as a "dummy" reference -> synchronize(lock){// Code with variable}.

    This still did not work. Currently the servlet behaves as if there are no synchronized blocks at all. Help is hugely appreciated!

  2. #2
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,756

    Re: Synchronizing on servlet instance variable

    4 instances of the servlet running
    If that were the case there would not be any collisions between the different instances of the class except for static variables.
    Each instance has its own set of fields.

    This still did not work
    Please explain what happens that makes you say "did not work".

    using a Thread.currentThread().sleep(10000) delay timer within the synchronized(){} block.
    That should hold the lock for 10 seconds preventing other threads from entering the block.

    instance (state) variables in servlets, but my college assignment calls strictly for this.
    I don't know when new instances of servlets are created. I new instances are created, the values held in class fields will be lost.
    Last edited by Norm; September 22nd, 2017 at 11:00 AM.
    Norm

  3. #3
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,756

    Re: Synchronizing on servlet instance variable

    Last edited by Norm; September 23rd, 2017 at 06:45 PM.
    Norm

  4. #4
    Join Date
    Sep 2017
    Posts
    15

    Re: Synchronizing on servlet instance variable

    Hey Norm.

    By "did not work" I meant a second thread of the servlet did not wait at all for the 10-second delay imposed in the synchronized code to elapse before it could proceed to work on the variable. I did the following to test whether the synchronization works:

    1) Start two threads of the servlet.
    2) In the one thread I enter an amount and click "Deposit", which adds this amount to the current total.
    3) Quickly switching over to the other thread, I click in it the "Balance" button, which brings up the current balance to screen.

    If all worked as intended, then unless 10 seconds passed, the second thread should display the same initial balance that both threads saw in the first place. The problem is, the second thread already immediately displays the updated balance (per what is added in thread 1) - so the delay timer and synchronization aren't functioning.

    I also tested the said delay timer code syntax for myself in a separate little program, outputting numbers to the screen and inserting the delay code syntax between one of the numbers. The output paused for 10 seconds between 2 of the numbers, so I confirmed that there is nothing wrong with the Thread.currentThread().sleep(10000); command. The issue is then with how I use synchronization...

  5. #5
    Join Date
    Jun 1999
    Location
    Eastern Florida
    Posts
    3,756

    Re: Synchronizing on servlet instance variable

    You need to post the new code.
    Norm

  6. #6
    Join Date
    Sep 2017
    Posts
    15

    Re: Synchronizing on servlet instance variable

    Code:
    // Import servlet and HTTP functionality packages.
    import javax.servlet.*;
    import javax.servlet.http.*;
    
    // Import packages to: handle user inputs and outputs, enable usage of decimal formatting of numbers.
    import java.io.*;
    import java.util.*;
    import java.text.DecimalFormat;
    
    public class SyncBank extends HttpServlet	// Define concrete class and extend HTTP functionality.
    {
    	// Declare class scope (instance) variables.
    	double balance;						// The current balance variable, un-formatted number.
    	String formattedBal;				// The current balance variable, formatted to show as currency amount.
    
    	public void init() throws ServletException	// Initialise variables at start of the servlet. Possible exception.
    	{
    		balance = 0;			// Initialise current un-formatted balance to 0.
    		formattedBal = "";		// Initialise current formatted balance to be blank.
    	}
    
    	// The method to output the initial HTML form to the screen, addressing also possible exceptions.
    	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    	{
    		showBalance(response);	// Call custom-defined method.
    	}
    
    	// Method to respond to user's button inputs - output relevant HTML back to the screen. Possible exceptions.
    	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    	{
    		response.setContentType("text/html");		// Set response type to text/HTML.
    		response.setHeader("Expires", "Tues, 01 Jan 1980 00:00:00 GMT");	// Set past date to forbid cache.
    
    		// If user clicks "Deposit" button:
    		if(request.getParameter("depButton") != null && request.getParameter("depButton").equals("Deposit"))
    		{
    			if(verifyAmount(request))	// If entered amount passes verification.
    			{
    				addToBalance(request);			// Add the amount to current balance.
    				redisplayCurrentPage(response);		// Redisplay initial page.
    			}
    			else		// If entered amount does not pass verification.
    			{
    				showErrorPage(response);	// Display error page.
    			}
    		}
    
    		// If user clicks "Withdraw" button:
    		if(request.getParameter("withdrButton") != null && request.getParameter("withdrButton").equals("Withdraw"))
    		{
    			if(verifyAmount(request))	// If entered amount passes verification.
    			{
    				subtractFromBalance(request);	// Subtract the amount from current balance.
    				redisplayCurrentPage(response);		// Redisplay initial page.
    			}
    			else		// If entered amount does not pass verification.
    			{
    				showErrorPage(response);	// Display error page.
    			}
    		}
    
    		// If user clicks "Balance" button:
    		if(request.getParameter("balButton") != null && request.getParameter("balButton").equals("Balance"))
    		{
    			showBalance(response);		// Display current formatted balance on page.
    		}
    	}
    
    	public boolean verifyAmount(HttpServletRequest request)	// Method to verify entered amount, based on textbook criteria.
    	{
    		boolean amountValid = false;	// Declare and initiate a validity variable.
    
    		// If entered amount is not blank and is greater than zero, return validity as true. Else, return false.
    		if(request.getParameter("amount") != "" && Double.parseDouble(request.getParameter("amount")) > 0)
    			amountValid = true;
    		else
    			amountValid = false;
    
    		return amountValid;		// Return validity variable.
    	}
    
    	// Synchronized method to add amount to balance, addressing possible exception.
    	synchronized private void addToBalance(HttpServletRequest request) throws IOException
    	{
    		double userAmount = Double.parseDouble(request.getParameter("amount"));	// Declare and assign entered amount variable.
    
    		balance = balance + userAmount;		// Add the amount to current balance and overwrite current balance value.
    
    		// Delay a deposit for a visible amount of time.
    		try
    		{
    			Thread.currentThread().sleep(10000);	// Sleep for milliseconds.
    		}
    		catch(InterruptedException e)
    		{
    
    		}
    	}
    
    	// Synchronized method to subtract from balance. Possible exception.
    	synchronized private void subtractFromBalance(HttpServletRequest request) throws IOException
    	{
    		double userAmount = Double.parseDouble(request.getParameter("amount"));	// Declare and assign entered amount value.
    
    		balance = balance - userAmount;		// Subtract the amount from the balance and overwrite current balance value.
    	}
    
    	public void showBalance(HttpServletResponse response) throws IOException	// Method to output balance HTML page. Possible exception.
    	{
    		PrintWriter out = response.getWriter();		// Establish HTML writer object.
    
    		formatBalance();	// Format current balance for displaying.
    
    		out.println("<html>");
    			out.println("<hr>");		// Horizontal line.
    			out.println("<title>Online Bank ATM Simulator</title>");		// Title to show on browser title bar.
    			out.println("<h1 align = \"center\">Bank ATM Simulation</h1>");	// Page heading, centered on page.
    			out.println("<body onLoad = \"amount.focus()\">");				// Set focus to the text-field.
    				out.println("<form method = \"POST\" action = \"../servlet/HTMLBank\">");	// Form method and submission address.
    					out.println("<center>");		// Tag to center the following output on page.
    					out.println("Amount: ");
    					out.println("<input type = \"text\" name = \"amount\" id = \"amount\" size = \"20\"><br><br>");	// Amount text field.
    					out.println("Balance: ");
    					out.println(formattedBal + "<br><br>");	// Current formatted balance shown.
    					out.println("<button name = \"balButton\" value = \"Balance\">Balance</button>");	// "Balance" button.
    					out.println("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");	// Spacers.
    					out.println("<button name = \"depButton\" value = \"Deposit\">Deposit</button>");	// "Deposit" button.
    					out.println("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");	// Spacers.
    					out.println("<button name = \"withdrButton\" value = \"Withdraw\">Withdraw</button>");	// "Withdraw" button.
    					out.println("</center>");		// Tag to end centering of output on page.
    				out.println("</form>");		// End of form.
    			out.println("</body>");
    			out.println("<br>");
    			out.println("<hr>");		// Horizontal line.
    		out.println("</html>");
    	}
    
    	// Method to redisplay form after deposit/withdrawal.
    	public void redisplayCurrentPage(HttpServletResponse response) throws IOException
    	{
    		PrintWriter out = response.getWriter();		// Establish HTML writer object.
    
    		out.println("<html>");
    			out.println("<hr>");		// Horizontal line.
    			out.println("<title>Online Bank ATM Simulator</title>");		// Title to show on browser title bar.
    			out.println("<h1 align = \"center\">Bank ATM Simulation</h1>");	// Page heading, centered on page.
    			out.println("<body onLoad = \"amount.focus()\">");				// Set focus to the text-field.
    				out.println("<form method = \"POST\" action = \"../servlet/HTMLBank\">");	// Form method and submission address.
    					out.println("<center>");		// Tag to center the following output on page.
    					out.println("Amount: ");
    					out.println("<input type = \"text\" name = \"amount\" id = \"amount\" size = \"20\"><br><br>");	// Amount text field.
    					out.println("Balance: ");
    					out.println("<br><br>");	// No formatted balance value shown.
    					out.println("<button name = \"balButton\" value = \"Balance\">Balance</button>");	// "Balance" button.
    					out.println("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");	// Spacers.
    					out.println("<button name = \"depButton\" value = \"Deposit\">Deposit</button>");	// "Deposit" button.
    					out.println("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");	// Spacers.
    					out.println("<button name = \"withdrButton\" value = \"Withdraw\">Withdraw</button>");	// "Withdraw" button.
    					out.println("</center>");		// Tag to end centering of output on page.
    				out.println("</form>");		// End of form.
    			out.println("</body>");
    			out.println("<br>");
    			out.println("<hr>");		// Horizontal line.
    		out.println("</html>");
    	}
    
    	synchronized private void formatBalance()	// Synchronized method to format the current balance number to a currency amount.
    	{
    		DecimalFormat dollars = new DecimalFormat("$###,###.###");	// Construct new decimal format.
    
    		formattedBal = dollars.format(balance);	// Format the current balance number.
    	}
    
    	// Method to output error HTML page, if entered amount does not pass verification. Possible exception.
    	public void showErrorPage(HttpServletResponse response) throws IOException
    	{
    		PrintWriter out = response.getWriter();		// Establish HTML writer object.
    
    		out.println("<html>");
    			out.println("<head>");
    				out.println("<title>Amount Input Error</title>");	// Title to show in browser title bar.
    			out.println("</head>");
    
    			out.println("<body>");
    				out.println("<h1>Error processing the input.</h1><br>");	// Heading text.
    				out.println("Please ensure your input:<br><br>");
    				out.println("- Is not blank.<br>");
    				out.println("- Is strictly a number.<br>");
    				out.println("- Is a positive, non-zero amount.");
    			out.println("</body>");
    		out.println("</html>");
    	}
    
    	public void destroy()	// Method to terminate the servlet.
    	{
    
    	}
    }
    Last edited by 2kaud; September 26th, 2017 at 04:48 AM.

  7. #7
    Join Date
    Aug 2017
    Posts
    32

    Re: Synchronizing on servlet instance variable

    The first solution is to avoid declaring servlet variables at the instance level by either passing objects from method to method or declaring variables local to a method. The clientRequest variable has been eliminated, and the username and password variables are local to the displayWelcomMessage() method.

  8. #8
    Join Date
    Sep 2017
    Posts
    15

    Re: Synchronizing on servlet instance variable

    Priya456, that is a good suggestion, and this IS my next task indeed. But for this task in discussion, I need to do it the way described, and that is to use a class scope (instance) variable.

  9. #9
    Join Date
    Sep 2017
    Posts
    15

    Re: Synchronizing on servlet instance variable

    The next task I am to do indeed instructs to remove instance variables and use session attributes, with which no synchronization is needed and multiple threads will not interfere with one another.

    But the current task in discussion instructs me to synchronize access to this instance variable. Is there then really no way to achieve this?

  10. #10
    Join Date
    Sep 2017
    Posts
    15

    Re: Synchronizing on servlet instance variable

    Any ideas? Thanks.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This a Codeguru.com survey!


On-Demand Webinars (sponsored)