Return-Path: Delivered-To: apmail-jakarta-struts-user-archive@apache.org Received: (qmail 20479 invoked from network); 20 Dec 2002 08:17:46 -0000 Received: from exchange.sun.com (HELO nagoya.betaversion.org) (192.18.33.10) by daedalus.apache.org with SMTP; 20 Dec 2002 08:17:46 -0000 Received: (qmail 16323 invoked by uid 97); 20 Dec 2002 08:18:29 -0000 Delivered-To: qmlist-jakarta-archive-struts-user@jakarta.apache.org Received: (qmail 16210 invoked by uid 97); 20 Dec 2002 08:18:28 -0000 Mailing-List: contact struts-user-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Struts Users Mailing List" Reply-To: "Struts Users Mailing List" Delivered-To: mailing list struts-user@jakarta.apache.org Received: (qmail 16081 invoked by uid 98); 20 Dec 2002 08:18:28 -0000 X-Antivirus: nagoya (v4218 created Aug 14 2002) Reply-To: From: "Andrew Hill" To: "Struts Users Mailing List" Subject: RE: multithreaded env Date: Fri, 20 Dec 2002 16:20:33 +0800 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0) X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4522.1200 Importance: Normal In-Reply-To: <001f01c2a7f6$29b0a0f0$ad03a8c0@d2s.com> X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N A webapp running in a servlet container (this includes any struts app) is by nature multithreaded. As you know, in a struts app most of the work is done not in servlets you implement, but rather in Action classes. These are also multithreaded. Struts will create a single instance of your Action and all requests for that Action will be processed by that instance. This means that at any given moment you could have any number of threads simultaneously running that Action's code. The implication of this is that you have to be careful of what you do with class member variables. (ie. Dont use them!) for example, consider the following rather contrived Action: public class WotsitAction extends Action { private String _foo; //member variable - Dangerous! public ActionForward execute(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws Exception { WotsitForm wotsitForm = (WotsitForm)form; _foo = wotsitForm.getFoo(); //line 1 doSomething(_foo); //line 2 //etc.... } } Now let us imagine we have two users who both submit different values for foo at nearly the same instant. User A submits a value of "A", and User B submits a value of "B". Let us assume that user A submits first. The action code is invoked and line 1 causes _foo to be set to "A". Meanwhile user B has also submitted. His request goes to the same instance of the WotsitAction. Let us imagine that user B's thread executes line 1 a picosecond after user A, just before user A's thread starts line 2. As a result _foo is now set to "B", because both threads are sharing the same action instance and thus the same _foo variable. Now BOTH users threads will be using the value of "B" to doSomething(). This is obviously not what we intended... Whats rather scary about this is that the errors that will result may well not be picked up in your basic testing, but rather will surface much later when load testing is conducted, or even worse when the app is in production. They will be intermittent errors and could take a considerable amount of time to track down... In this example for the code to work as intended it is necessary that the member variable _foo is replaced by a method variable. Ie: public class WotsitAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws Exception { WotsitForm wotsitForm = (WotsitForm)form; String foo = wotsitForm.getFoo(); //line 1 doSomething(foo); //line 2 //etc.... } } In this case both threads still share the action instance, but foo is now local to the execute method and each thread has its own foo. Things will now work as intended... Basically dont use class member variables in your actions (unless you are specifically intending to share information between threads with them. Even in that case it would not be a good idea as you have other such considerations as clustering, the need to synchronize reads and writes etc...). Now you may be thinking you could instead of refactoring all that code in the first version of WotsitAction just make the execute & other public methods synchronized, and indeed you technically could. That however has nasty performance implications. Imagine the execute() method takes 10 seconds to do its thing. Imagine also that 6 users submit at once. With execute synchronized, only one of the threads can be executing the synchronized code at a time. Some of those users could be waiting up to a minute for their request to complete... Furthermore thread wakeup notification doesnt happen in any particular order. If lots more requests keep pouring in all the time its conceivable some request threads could 'never' get a chance to run execute()!!!! These sort of issues need to be considered for any shared objects. For example stuff you put into ServletContext can be accessed by many threads at the same time. Likewise with stuff in the SessionContext. The request context on the other hand is not shared with other threads (unless you make your own threads - (dont do that in a webapp! - its naughty)). Request scoped actionform instances are therefore unique to that request. Session scoped actionforms may be 'problematic' under some circumstances. (Refer to my discussion in this list with Eddie recently under the thread "Multiple forms in session" to see why) -----Original Message----- From: Amit Badheka [mailto:amit@direct2s.com] Sent: Friday, December 20, 2002 15:05 To: Struts Users Mailing List Subject: multithreaded env Hi All, I am working on a struts application. But I am not sure that it will work properly in multithreaded environment. Can anybody suggest me what is the best way to make sure that application work fine in such environment. Thank You. -- To unsubscribe, e-mail: For additional commands, e-mail: