Section 11.1. Synchronization and

   

11.1 Synchronization and <cflock>

Synchronization is Java's way of keeping shared objects from getting corrupted when competing operations are being performed on them. This should be a familiar concept from ColdFusion and from database design.

In ColdFusion you store, for example, variables in the Session scope. Any time you read or write data from the Session, Application, or Server scopes in ColdFusion you must lock those variables . That's because data stored in these scopes is memory resident. While that makes them very fast to access, it also makes them vulnerable to data corruption if two competing operations were to access the same data at the same time and perform some conflicting operation.

In order to prevent this kind of corruption, you lock your variables using the <cflock> tag. This should be a familiar operation:

 <cflock scope="session" timeout="20">          <cfset Session.BankAccount.Balance = getbalance.Amount> ....perform a withdrawal, and a deposit         <cfoutput>#Session.BankAccount.Balance#</cfoutput> </cflock> 

Now what if the above code were not locked? Another thread (process) could modify the balance between data retrieval and display and the data would be inaccurate. <cflock> answers this problem in ColdFusion. The keyword synchronized handles it in Java.

The synchronized keyword locks Java objects. When a processing thread encounters a synchronized block of code, one of two things happen: It determines that no other process is currently accessing the code block, so it obtains a lock. Alternatively, it may discover that another process is currently inside that code block, in which case it will wait for that process to complete.

Note

Sometimes these locks are called monitors .


Once a process is through executing its business inside the synchronized block, it releases the lock it held so that other processes may access it.

11.1.1 Thread Safety with synchronized

Adding the synchronized keyword to a method will cause the operation to which you prefix it to be locked. The structure is like this:

 synchronized public void someMethod() {...} 

Notice that this is syntactically different from ColdFusion, in which you lock data that accesses a memory-resident scope ( Session.someValue ). In Java, you lock the operation you want to keep thread-safe ( synchronized someMethod() ). The Java syntax is closer, perhaps, to something you may be familiar with from working with relational databases: isolation implemented with locks. Database isolation prevents two competing data reads or modifications from happening at once, just like we've been talking about. Locks in a database ensure that one user 's changes to some data do not access it, possibly getting a "dirty" or "phantom" read. While it looks as if it is the method itself that is synchronized, that wouldn't really make sense when you think about it. Only objects are actually synchronized, because objects are the repository for data. There are a couple of rules that are easy to remember about synchronization:

  • Multiple threads can execute the same method at the same time ”as long as they are all operating on different objects.

  • Multiple threads cannot concurrently execute different synchronized methods if they are operating on the same object.

Note that there are times when it is not possible to declare a method as synchronized ” generally when someone else created the class. The way around this is to synchronize the object directly, using this statement:

 synchronized(anObject) {      //...code to be synchronized             } 

Let's have a quick look at implementing thread safety with the following example. This example will demonstrate not only how to keep your data safe using the synchronized keyword, but it will help us get a little practice with implementing interfaces, as we learned how to do in Chapter 9. The following example implements the Runnable interface, which is an abstract method of java.lang.Thread .

11.1.2 SynchTest.java

 /*   * SynchTest.java  *  */ package chp11; public class SynchTest implements Runnable  {    private Account a = new Account();    public static void main (String[] args) {        SynchTest sT = new SynchTest();             // create two threads        Thread first = new Thread(sT);        Thread second = new Thread(sT);             // start them running        first.start();        second.start();        System.out.println("transaction complete...");      }         /* This class uses the Runnable interface,          * so we must implement the abstract run() method.          * We want to synch the modifying and accessing of          * the account. No other thread can enter the method          * until all code inside it is executed.          */     public void run() {          // starting balance         double startBalance = a.getBalance();             for (double i = 0; i < 10000 ; i++) {                     // all code inside here is locked                 synchronized(this) {                     // add money                     a.deposit (100);                     // subtract money                     a.withdraw (100); // this method causes the thread to pause temporarily and let // other threads execute                     Thread.yield();                     if (startBalance != a.getBalance())                        System.out.println("threads collided");                 }             }     } } 

This code synchronizes the object passed into it while the deposit and withdraw operations are performed. If the account object were not locked, then there would be an opportunity somewhere among our 10,000 iterations of the loop for one of the threads to make a lone deposit or withdrawal operation ”which would mean the balance would not be reconciled, and the error message would be printed.

Account.java is the simplest possible account, which has a starting balance of $50, and methods for making a deposit and a withdrawal.

11.1.3 Account.java

 package chp11;  public class Account {     private double balance;         // constructor sets balance at      public Account() {         balance = 50;     }     public double getBalance() {         return balance;     }     public void deposit(double dep) {         balance += dep;     }     public void withdraw(double withdraw) {         balance -= withdraw;     } } 

This brief overview shows you how to lock operations that you need to be thread safe. Some Collections can be synchronized, which gives us reason to discuss this here. Depending on your project, there can be many subtle and important aspects of dealing successfully with threads. Consult the API for more information regarding threads.

In the following section we will recall how to use ColdFusion structures in order to set the table for our discussion of Collections.


   
Top


Java for ColdFusion Developers
Java for ColdFusion Developers
ISBN: 0130461806
EAN: 2147483647
Year: 2005
Pages: 206
Authors: Eben Hewitt

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net