在Java中使用Semaphore和Monitor的IllegalMonitorException

时间:2009-12-30 06:36:39

标签: java

我的“操作系统”项目。我需要用java编写2个程序...

  1. 编写一个程序,用2种方法氧气和氢气生产水。 方法氧气产生一氧气和方法氢气产生一个氢气。当存在2个氢和一个氧时,产生H 2 O.我必须用信号量和线程来写这个。

  2. 使用Monitors和Sychronize编写上述问题。

  3. 我已为此编写了一些代码,但它提供了非法的监视器执行... 请帮我纠正一下......

    这是我的代码:

    // class for implement Thread for oxygen
    public class Thread_O implements Runnable {
    
        public void run() {
    
            thread t = new thread();
    
            try {
                t.oxygen();
            } catch (InterruptedException ex) {
                Logger logger = Logger.getLogger(Thread_O.class.getName());
                logger.log(Level.SEVERE, null, ex);
            }
        }
    }
    
    
    // class for implement Thread for Hydrogen
    public class Thread_H implements Runnable {
    
        public void run() {
    
            thread t = new thread();
    
            try {
                t.Hydrogen();
            } catch (InterruptedException ex) {
                Logger logger = Logger.getLogger(Thread_H.class.getName());
                logger.log(Level.SEVERE, null, ex);
            }
        }
    }
    
    //class for method Oxygen and Hydrogen
    public class thread {
    
        Semaphore O = new Semaphore(0, true);
        Semaphore H = new Semaphore(0, true);
        Semaphore H2O = new Semaphore(0, true);
        Semaphore safe = new Semaphore(1, true);
    
        public void oxygen() throws InterruptedException {
    
            safe.wait();
    
            H.wait();
            H.wait();
    
            H2O.release();
            H2O.release();
    
            Safe.release();
            //  System.out.println("O2...!");
        }
    
        public void Hydrogen() throws InterruptedException {
    
            H.release();
            H2O.wait();
    
            //   System.out.println("H2...!");
        }
    }
    

    并且在氧气按钮的作用下:

        Thread th = new Thread(new Thread_O());
        th.start();
    

3 个答案:

答案 0 :(得分:3)

我不打算为你解码你的作业,但是当你试图wait()对象而不是synchronized时会抛出IllegalMonitorException。所以要等待一个名为list的对象:

synchronized (list) {
   try {
      list.wait();
   } catch(Throwable t) {
      t.printStackTrace();
   }
}

答案 1 :(得分:2)

您必须了解生产者/消费者机制的运作方式。

在这里,您将拥有一个消费者线程和两个生产者。

首先,您将有一个生产氧气的螺纹,以及其他生产氢气的螺纹。

那么,那些分子应该在“某个地方”好吗?那个“东西”是必须被监控和同步的东西。

所以它应该是这样的:

 class Water { 
     char [] waterMolecule = new char[3]; // <-- synchronize access to this
     char hydrogen(){ 
         return 'H';
     }
     char oxygen() {
         return 'O';
     }

     void produce() {
         Thread t = new Thread( new Runnable() {
               synchronize( waterMolecule ) { 
                      waterMolecule[0] = hydrogen();
               }
          }):
          .... produce the others 


      }

      void consume() {
         synchronize watermolecule 
          if waterMolecule is complete 
              create water and clean out the molecule.
      }
  }

这是基本的想法。

请记住,在前一个氧气被消耗之前,你将无法产生另一个氧气颗粒。

此外,您必须始终在while循环中调用wait

Here's应该如何编码等待/同步。

Here's许多生产者/消费者样本。

答案 2 :(得分:1)

虽然您的作业已经完成,但我想建议CyclicBarrier作为此方案的最佳解决方案。 它允许不同线程的某种会合(这里:你的分子生成器)并触发在completition上执行额外的runnable(这里:创建h20)。