All ITKnowledge Source Code Search Tips Advanced Search |

| Mastering Java Threads by Marc Adler and David Herst DDC Publishing, Inc. ISBN: 1562438425 Pub Date: 05/01/99

Search this book:

Previous | Table of Contents | Next

The PingPong object uses the variable whoseTurn as a gate to the section of code that simulates hitting the ball. If, for some reason, the wrong thread gets into the hit function, it is forced to wait until the other thread wakes it up.

GAME.JAVA

    public class Game

    {

       public static void main(String args[])

       {

          PingPong table = new PingPong();

          Thread alice = new Thread(new Player(“bob”, table));

          Thread bob = new Thread(new Player(“alice”, table));

          alice.setName(“alice&3148;);

          bob.setName(“bob&3148;);

          alice. start(); // alice starts playing

          bob.start(); // bob starts playing

          try

          {

             // Wait 5 seconds

             Thread.currentThread().sleep(5000);

          }

          catch (InterruptedException e)

          {

          }

          table.hit(“DONE&3148;); // cause the players to quit their
    threads.

          try

          {

             Thread.currentThread().sleep(100);

          }

          catch (InterruptedException e)

          {

          }

       }

    }

PLAYER.JAVA

    public class Player implements Runnable

    {

        PingPong myTable;   // Table where they play

        String myOpponent;

        public Player(String opponent, PingPong table)

       {

          myTable   = table;

          myOpponent = opponent;

       }

       public void run()

       {

         while (myTable.hit(myOpponent))

           ;

       }

    }

PINGPONG.JAVA

    public class PingPong

    {

        // state variable identifying whose turn it is.

        private String whoseTurn = null;

        public synchronized boolean hit(String opponent)

       {

          String x = Thread.currentThread().getName();

         if (whoseTurn == null)

         {

            whoseTurn = x;

            return true;

         }

         if (whoseTurn.compareTo (“DONE”) == 0)

           return false;

         if (opponent.compareTo (“DONE”) == 0)

         {

           whoseTurn = opponent;

           notifyAll();

           return false;

         }

         if (x.compareTo (whoseTurn) == 0)

         {

           System.out.println(“PING! (“+x+”) ”);

           whoseTurn = opponent;

           notifyAll();

         }

         else

         {

          try

          {

            long t1 = System.currentTimeMillis();

            wait (2500);

            if ((System.currentTimeMillis() - t1) > 2500)

            {

              System.out.println(

                “****** TIMEOUT! ” + x +

                “ is waiting for “+whoseTurn+” to play.”);

            }

          }

          catch (InterruptedException e)

         {

         }

       }

       return true; // keep playing.

      }

    }

### Deadlock

Deadlock is a situation in which multiple threads are waiting on multiple locks to be freed, but those locks will never be (or are never) freed. Below is a simplistic example of deadlock.

    public void father()

    {
        synchronized(respect)

       {

         respect.get();

         synchronized (allowance)

         {

            allowance.give();

         }

       }

    }

    public void son()

    {

        synchronized(allowance)

       {

          allowance.get();

          synchronized(respect)

         {

            respect.give();

         }

       }

    }

#### Example Analysis

Once the father object gets respect, he will lock the allowance object, deposit some money into it, and then release it. However, the only way that the son object will unlock the respect object is if he gets the allowance object. In this example, you can see that the father and son objects have locks on objects that the other needs in order to proceed. The application will be in a deadly, infinite embrace waiting for the locks to be freed.

| This is the classic “which came first, the chicken or the egg?” scenario.

#### Difficult to Detect

Deadlock is very difficult to detect. Java does not contain any type of automated functions to detect deadlock, nor does Java contain any kind of run-time deadlock detection.

There are two ways to avoid deadlock:

  1. One synchronized method should never call another synchronized method. This rule is often impractical in the real world. Java contains synchronized methods (such as Vector.addElement()) that you will call from your own synchronized methods.
  2. Use some sort of higher-level object to be locked. For example, you might have a Family object declared as follows:

    class Family

    {

          public synchronized father();

          public synchronized son();

    ...

    }

The problem with the above example is that the locking granularity might be too large. For example, with the class above, the other sons and daughters might not be able to get their allowance until the obstinate son relinquishes and gives respect to the father.

The best way to avoid deadlock is to ensure that locks are always acquired in the same order. In the previous example, the lock for the respect object would be acquired before the lock for the allowance object.

Lab 4: Bringing It All Together—A Final Exercise

In the preceding Lesson, you learned about synchronization issues and how to share a single resource among multiple threads.

In this Lab, write a Java program to simulate the following (albeit unrealistic) scenario:

  • you live in a city that has 5 telephones but only one “connection.”
  • You can divide the 5 phones into 3 callers and 2 receivers.
  • A caller can only connect to a receiver.
  • When a caller dials a number, there might be another party using the line. Therefore, the caller and the corresponding receiver must wait until the connection becomes free before they can communicate with each other.
  • When two parties finally do connect with each other, all other callers and receivers are locked out of the connection until the conversation is finished.

There are many ways to model this Java problem; feel free to express your creativity. There is no right or wrong way of approaching this programming challenge. You should use everything you have learned in this course to create this application. If necessary, review various sections of this course.

As an additional exercise, you can generalize your solution so that it will work if you decide to add n connections to your surrealistic phone network.

Previous | Table of Contents | Next

Copyright © DDC Publishing

Products | Contact Us | About Us | Privacy | Ad Info | Home Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.