Java - Threads and monitors

Sahir Shah
November-1999

 When two or more threads share a common resource  they access the shared object in an asynchronous manner. This asynchronous behaviour often leads to conflicts between threads. For example a  thread may write data to an object while another thread is reading from the object. This may introduce errors into the program.  Hence the programmer must enforce synchronous access to shared objects.  When a block of code is marked  as synchronized the runtime system ensures that only one thread can access that block of code at the same time i.e that particular bit of code can only be accessed in a synchronised manner.  The synchronized keyword can be used to qualify an entire method or a block code within a method.  The shared object which contains the synchronised code is called a  monitor.  The monitor is able to pause and release a thread by calling the methods wait() and notify(). The methods wait() , notify() and notifyAll() are members of class Object and are thus available to all objects. A monitor can calll wait and pause the execution of mutiple threads. The method notifyAll(); releases all the threads currently paused by the monotor. The following example applet demonstrates the locking and releasing of threads by a monitor object.

      import java.awt.*;
      import java.awt.event.*;
      import java.applet.*;
      class  SynchTest extends Frame implements Runnable{
        Panel panel            = new Panel();
        java.awt.List list1    = new java.awt.List();
        Button btnStart        = new Button(" Start ");
        Button btnStop         = new Button(" Stop ");
        Button btnClear        = new Button(" Clear ");
        Button btnClose        = new Button(" Close ");
        SynchObject synchObj   = new SynchObject();
        String threadName;
        public static void main(String[] args){
          SynchTest st = new SynchTest();
          GUIHelper.layout(st);
          GUIHelper.addListeners(st);
          st.setSize(550,300);
          st.validate();
        }

        public void run(){
          synchObj.enterLock(this , threadName);
        }

        public void btnStartClick(){
          Thread thr = new Thread(this);
          threadName = thr.getName();
          thr.start();
        }

        public void btnStopClick(){
           threadName = Thread.currentThread().getName();
           synchObj.release(this, threadName);
        }

         public void btnClearClick() {
            list1.removeAll();
         }
      }


      class SynchObject{
         synchronized void enterLock(SynchTest st , String name){
            st.list1.add(name +  " enters monitor");
            try {wait();}
            catch(InterruptedException e) {}
            st.list1.add(name +  " exits monitor");
         }
         synchronized void release(SynchTest st , String name){
            notifyAll();
            st.list1.add(name + " calling notify");
         }
      }


       class GUIHelper{
          static void layout(SynchTest  st){
             st.setVisible(true);
             st.add(st.list1, BorderLayout.CENTER);
             st.add(st.panel,BorderLayout.SOUTH);
             st.panel.add(st.btnStart);
             st.panel.add(st.btnStop);
             st.panel.add(st.btnClear);
             st.panel.add(st.btnClose);
             st.setLocation(300,300);
          }

          static void addListeners(final SynchTest st){
               st.btnStart.addMouseListener(new MouseAdapter(){
                       public void mouseClicked(MouseEvent e){
                        st.btnStartClick();
                      }});
               st.btnStop.addMouseListener(new MouseAdapter(){
                       public void mouseClicked(MouseEvent e){
                        st.btnStopClick();
                      }});
               st.btnClear.addMouseListener(new MouseAdapter(){
                       public void mouseClicked(MouseEvent e){
                        st.btnClearClick();
                      }});
              st.btnClose.addMouseListener(new MouseAdapter(){
                      public void mouseClicked(MouseEvent e){System.exit(0);}});
          }
       }

Home