|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 5 of 7
Tip: When you need to determine if a thread holds a given object's associated lock, call Thread's static boolean holdsLock(Object o) method. That method returns a Boolean true value if the thread calling that method holds the lock associated with the object
that o references; otherwise, false returns. For example, if you were to place System.out.println (Thread.holdsLock (ft)); at the end of SynchronizationDemo1's main() method, holdsLock() would return false. False would return because the main thread executing the main() method does not use the synchronization mechanism to acquire any lock. However, if you were to place System.out.println (Thread.holdsLock (ft)); in either of run()'s synchronized (ft) statements, holdsLock() would return true because either the deposit thread or the withdrawal thread had to acquire the lock associated with the
FinTrans object that ft references before that thread could enter its critical code section.
You can employ synchronized statements throughout your program's source code. However, you might run into situations where excessive use of such statements
leads to inefficient code. For example, suppose your program contains a method with two successive synchronized statements that each attempt to acquire the same common object's associated lock. Because acquiring and releasing the object's
lock eats up time, repeated calls (in a loop) to that method can degrade the program's performance. Each time a call is made
to that method, it must acquire and release two locks. The greater the number of lock acquisitions and releases, the more
time the program spends acquiring and releasing the locks. To get around that problem, you might consider using a synchronized
method.
A synchronized method is either an instance or class method whose header includes the synchronized keyword. For example: synchronized void print (String s). When you synchronize an entire instance method, a thread must acquire the lock associated with the object on which the method
call occurs. For example, given an ft.update("Deposit", 2000.0); instance method call, and assuming that update() is synchronized, a thread must acquire the lock associated with the object that ft references. To see a synchronized method version of the SynchronizationDemo1 source code, check out Listing 3:
// SynchronizationDemo2.java
class SynchronizationDemo2
{
public static void main (String [] args)
{
FinTrans ft = new FinTrans ();
TransThread tt1 = new TransThread (ft, "Deposit Thread");
TransThread tt2 = new TransThread (ft, "Withdrawal Thread");
tt1.start ();
tt2.start ();
}
}
class FinTrans
{
private String transName;
private double amount;
synchronized void update (String transName, double amount)
{
this.transName = transName;
this.amount = amount;
System.out.println (this.transName + " " + this.amount);
}
}
class TransThread extends Thread
{
private FinTrans ft;
TransThread (FinTrans ft, String name)
{
super (name); // Save thread's name
this.ft = ft; // Save reference to financial transaction object
}
public void run ()
{
for (int i = 0; i < 100; i++)
if (getName ().equals ("Deposit Thread"))
ft.update ("Deposit", 2000.0);
else
ft.update ("Withdrawal", 250.0);
}
}
Though slightly more compact than Listing 2, Listing 3 accomplishes the same purpose. If the deposit thread calls the update() method, the JVM checks to see if the withdrawal thread has acquired the lock associated with the object that ft references. If so, the deposit thread waits. Otherwise, that thread enters the critical code section.