Presents your JAVA E-NEWSLETTER for January 15, 2004 <-------------------------------------------> MAKING A CLASS THREAD-SAFE In Java applications, creating multiple threads of execution is a simple matter of creating instances of java.lang.Thread and calling the start method. But it isn't always easy to get the results you expect out of your multithreaded application. Here are a few things to keep in mind when creating asynchronous programs. Instance variables are thread-unsafe by default. Even if you only consider instance variables that are declared as private, the variables can still be manipulated and inspected by any method of that instance. If unsynchronized methods are called simultaneously by two different threads, either thread can manipulate the variables at any time. For instance, take the following code: 1 class Account { 2 private int balance; 3 4 public int withdraw(int amount) { 5 if ( balance >= amount ) { 6 balance -= amount; 7 return amount; 8 } 9 else { 10 return 0; 11 } 12 } 13 } Assuming that there are two threads (t1 and t2), both remove an amount equal to balance. If t1 calls the withdraw method and is forced to yield at line 6 after the balance check is made but before the actual withdraw action is taken, then t2 will pass the balance check and eventually execute the withdraw action. Now the account has a negative balance. The easiest way to solve this problem is to synchronize access to the withdraw method. Instance arguments are thread-safe by default. For example, in the following method: public void foo(int count) { ... } there will never be any confusion about which thread has what value of count no matter how many threads call the foo method at one time; each thread gets its own copy of the method parameters used when that thread made the call. If a method manipulates only the arguments passed to it, the method is automatically thread-safe. Synchronize only what needs to be synchronized. Some programmers--after experiencing a problem related to synchronization or the lack thereof--begin to synchronize everything. Resist that temptation. Synchronization brings with it a significant amount of overhead, even if there's just one thread ever accessing an object. Keep in mind that not all code needs to be thread-safe because it may not ever run in a multithreaded environment. Premature thread safety (like premature optimization) rarely delivers the results you expect. David Petersheim is the Director of Application Development with Genscape, Inc. He designs and develops server-side applications to acquire and process real-time energy data. ----------------------------------------