18.5 THREAD SYNCHRONIZATION IN JAVA


18.5 THREAD SYNCHRONIZATION IN JAVA

Java provides a simple-to-use mechanism to prevent thread interference. Methods that require access to shared data are declared synchronized. Only one thread at a time is allowed to execute the code in a synchronized method, all other threads must wait. A thread that is executing a synchronized instance method acquires a lock on the object on which the method is invoked. When the synchronized method finishes executing, the thread relinquishes its lock on the object. Only one thread may have a lock on an object at any time. Therefore, during the time a thread has a lock on an object, that object is not accessible to any other threads-even via the other methods that might be defined for that object. In other words, if an object possesses several synchronized methods, only one of them will be active at any given time. A thread that is executing a synchronized static method of a class obtains a lock on the class object.

Locking is achieved with the help of monitors. Every object with a synchronized instance method has associated with it a monitor. By the same token, every class with a static method also has a monitor. A thread becomes the owner of an object's monitor by executing one of its synchronized methods.[11] When a thread is done executing the synchronized method, it relinquishes its ownership of the monitor, which then becomes free to be owned by some other thread. Thread synchronization is achieved with the help of a monitor object maintaining a list of all threads waiting to execute any of its synchronized methods. The monitor then gives access to the waiting threads one at a time.

So to fix the thread interference problem in the UnsynchedSwap class of the previous section, all we have to do is to declare the itemSwap and the test methods synchronized, as we show below in the following thread-safe implementation of the earlier program:

 
//SynchedSwaps.java ////////////////////////// class DataObject ///////////////////////// class DataObject { int dataItem1; int dataItem2; DataObject() { dataItem1 = 50; dataItem2 = 50; } synchronized void itemSwap() { int x = (int) (-4.999999 + Math.random() * 10); dataItem1 -= x; keepBusy(10); dataItem2 += x; } synchronized void test() { int sum = dataItem1 + dataItem2; System.out.printIn(sum); } public void keepBusy(int howLong) { long curr = System.currentTimeMillis(); while (System.currentTimeMillis() < curr + howLong) ; } } //////////////////////// class RepeatedSwaps //////////////////////// class RepeatedSwaps extends Thread { DataObject dobj; RepeatedSwaps(DataObject d) { dobj = d; start(); } public void run() { int i = 0; while (i++ < 20000) { dobj.itemSwap(); if (i % 4000 == 0) dobj.test(); try { sleep(1); } catch(InterruptedException e) {} } } } ///////////////////////// class SynchedSwaps //////////////////////// public class SynchedSwaps { public static void main(String[] args) { DataObject d = new DataObject(); new RepeatedSwaps(d); new RepeatedSwaps(d); new RepeatedSwaps(d); new RepeatedSwaps(d); } }

The output of this program is free of errors:

     100     100     100     100     100     100     100     100     100     100     100     100     100     100     100     100     100     100     100     100 

The interference problem with the UnsynchedFileIO class of the previous section can be fixed in a similar manner-by making the method fileIO() synchronized. We have shown below the source code for a class SynchedFileIO. This code is the same as for UnsynchedFileIO except that the method fileIO() is now synchronized:

 
//SynchedFileIO.java /////////////////////////// class DataFile ////////////////////////// class DataFile { public DataFile() { try { FileIO.writeOneString("Hello", "hello.dat"); } catch(FileIOException e) {} } synchronized void fileIO() { try { String str = FileIO.readOneString("hello.dat"); FileIO.writeOneString(str , "hello.dat"); } catch(FileIOException e) {} } } /////////////////////// class ThreadedFileIO /////////////////////// class ThreadedFileIO extends Thread { DataFile df; ThreadedFileIO (String threadName, DataFile d) { df = d; setName(threadName); start(); } public void run() { int i = 0; while (i++ < 4) { try { df.fileIO(); String str = FileIO.readOneString("hello.dat"); System.out.printIn(getName() + ": " + "hello.dat contains: " + str); sleep(5); } catch(InterruptedException e) {} catch(FileIOException e) {} } } } //////////////////////// class SynchedFileIO //////////////////////// public class SynchedFileIO { public static void main(String[] args) { DataFile dd = new DataFile(); new ThreadedFileIO("t0", dd); new ThreadedFileIO("t1", dd); new ThreadedFileIO("t2", dd); new ThreadedFileIO("t3", dd); new ThreadedFileIO("t4", dd); } }

The output produced by this program is also free of errors:

     t0:        hello.dat contains: Hello     t1:        hello.dat contains: Hello     t2:        hello.dat contains: Hello     t3:        hello.dat contains: Hello     t4:        hello.dat contains: Hello     t0:        hello.dat contains: Hello     t1:        hello.dat contains: Hello     t2:        hello.dat contains: Hello     t3:        hello.dat contains: Hello     t4:        hello.dat contains: Hello     t0:        hello.dat contains: Hello     t1:        hello.dat contains: Hello     t2:        hello.dat contains: Hello     t3:        hello.dat contains: Hello     t4:        hello.dat contains: Hello     t0:        hello.dat contains: Hello     t1:        hello.dat contains: Hello     t2:        hello.dat contains: Hello     t3:        hello.dat contains: Hello     t4:        hello.dat contains: Hello 

Before ending this section, we must mention that it is also possible to synchronize just blocks of code using the following syntax:

     synchronized(obj) {         // code     } 

where obj is the object to be locked. When synchonization protection is desired vis-à-vis the static members of a class, you'd need to supply the class itself as an argument to synchronized.

[11]A thread can also become the owner of an object's monitor by executing the body of a synchronized block of code that synchronizes on the object. The end of this section explains what is meant by a synchronized block of code in a method.




Programming With Objects[c] A Comparative Presentation of Object-Oriented Programming With C++ and Java
Programming with Objects: A Comparative Presentation of Object Oriented Programming with C++ and Java
ISBN: 0471268526
EAN: 2147483647
Year: 2005
Pages: 273
Authors: Avinash Kak

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