|
|
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 6 of 7
As I mentioned above, Wilma and Betty are a contrived example, but the multiple-lock situation comes up frequently. I'll give a more detailed example next month.
If all deadlock scenarios were as easy to recognize as Wilma and Betty, deadlock wouldn't be a problem. Consider the following code, though:
class Boss
{
private Side_kick robin;
public synchronized void set_side_kick( Side_kick kid_in_tights )
{ robin = kid_in_tights;
};
public synchronized void to_the_bat_cave()
{ robin.get_in_the_car();
}
public synchronized void okay() // sent to us by robin
{ //...
}
public synchronized void hold_on() // sent to us by robin
{ //...
}
}
//-------------------------------------------------------
class Side_kick
{
private Boss batman;
public synchronized void set_boss( Boss guy_in_cape )
{ batman = guy_in_cape;
}
public synchronized void get_in_the_car() // sent by batman
{ batman.okay();
}
public synchronized void sock_bam_pow() // sent from outside
{ batman.hold_on();
}
}
//-------------------------------------------------------
class Gotham_city
{ static Boss batman = new Boss();
static Side_kick robin = new Side_kick();
public static void main( String[] args )
{
batman.set_side_kick( robin );
robin.set_boss( batman );
// spawn off a bunch of threads that use batman and robin.
}
}
Now imagine the following:
to_the_bat_cave() request to the batman object passed to it from main().batman object starts to process the method, but is preempted just before it calls robin.get_in_the_car(). At this juncture, Alfred has acquired the lock for the batman object.sock_bam_pow() message to the robin object that it got from main().robin object (whose sock_bam_pow() method is running on the Joker thread) tries to send a hold_on() message to batman, but can't because Alfred owns the lock on batman. So the Joker thread is now blocked, waiting for Alfred to release the lock on batman.get_in_the_car() message to the robin object, but it can't because the Joker thread owns the lock on robin. Both threads are now deadlocked (sound familiar?)
Remember: threads own the locks and methods execute on threads, not objects.
This situation is, of course, much harder to see than the Wilma-and-Betty problem because the locks in the batman-robin example are the natural locks associated with individual objects. There are no standalone synchronized statements in the
batman-robin code, and the locks are associated with two completely distinct objects.
Multithreaded programmers tear their hair out looking for the causes of these sorts of problems, and there are only two solutions. The first is to thoroughly design the code before implementing it, and then to really study both the design and the implementation before you even think about running it the first time. When I do multithreaded programs, I spend much more time on code and design reviews than I spend on coding.