2017-11-01 9 views
-2

私は、0と1の単純なセマフォをセットアップしようとしています。ここで、wait()関数とSignal()関数はクリティカルセクションのスレッドのみを許可します。生産者と消費者のセマフォがメインで交互になっている実行クラスでヌルとしてセマフォを初期化する

static Semaphore lock = new Semaphore(-1); // create semaphore 
Consumer consumerSemaphore = new Consumer(lock); 
Producer producerSemaphore = new Producer(lock); 

は、スタック内の任意の異常を起こさないために、次のように

public class Producer extends BaseThread 
{ 
    Semaphore semaphore = null; 
    private char block; // block to be returned 

    public Producer(Semaphore x) 
    { 
     this.semaphore = x; 
    } 
    public Producer() 
    { 
     // empty constructor 
    } 
    public void run() 
    { 

     try{ 
      this.semaphore.wait(); // enter the critical section 
      for (int i = 0; i < 3; i++){ 
       this.block = StackManager.stack.pick(); 
       StackManager.stack.pick(); // return value on top 
       StackManager.stack.push(block++); // pushes the next char value on the stack 
      } 
     } 
     catch(Exception e){ 
      allException(e); 
      System.exit(1); 
     } 
     finally 
     { 
      this.semaphore.Signal(); // end critical section 
     } 

    } 
} 

セマフォがメインで宣言されています。 (Consumerクラスは本質的にProducerと同じように書かれていますが、代わりにpop()を実行するので、Consumerクラスは省略しました)。

ここでの問題は、コードを実行しているときにConsumerクラスとProducerクラスの両方でNullPointerExceptionエラーが発生し続けていることです。答えが見つからないようです。私はここで何が欠けていますか?

EDIT: コードはStackManager.stackの先頭の次のchar値をプッシュする必要がありますが、Consumerという別のクラスもpop()操作を行っているので、同期を実行する必要があります。

class Semaphore { 
    private int value; 

    public Semaphore(int value) { 
     this.value = value; 
    } 


    public Semaphore() { 
     this(0); 
    } 


    public synchronized void Wait() { 
     while (this.value >= 0) { //changed to greater or equals since we're doing the opposite with natural numbers 
      try { 
       wait(); 
      } 
      catch(InterruptedException e) { 
       System.out.println ("Semaphore::Wait() - caught InterruptedException: " + e.getMessage()); 
       e.printStackTrace(); 
      } 
     } 
     this.value++; // the semaphore value gets incremented since it needs to go to zero from -1 or lower 
    } 

    public synchronized void Signal() { 
     --this.value; // signal decrements the value since it brings the lock back to -1 for the next wait operation 
     notify(); 
    } 

    public synchronized void P() { 
     this.Wait(); 
    } 

    public synchronized void V() { 
     this.Signal(); 
    } 
} 

お知らせセマフォは、()-1として、当然の複雑さのために、私たちが必要とするので、メインで初期化されています。私は他の何かが、私が作成したこのクラスでセマフォを使用することはできませんSemaphoreクラスを作成します。-1は次のスレッドの準備ができていることを意味し、0はスレッドがクリティカルセクションにあることを意味します。これは、私がインクリメントとシグナルデクリメントを書いたwait()メソッドを意味します。

編集2:追加されましたConsumerクラス

public class Consumer extends BaseThread { 
    Semaphore semaphore = null; 
    private char copy; // A copy of a block returned by pop() 

    public Consumer(Semaphore x) { 
     this.semaphore = x; 
    } 

    public Consumer() { 
     // empty constructor 
    } 

    public void run() { 
     try { 
      this.semaphore.wait(); // enter the critical section 

      System.out.println("Consumer thread [TID=" + this.iTID + "] starts executing."); 
      for (int i = 0; i < StackManager.iThreadSteps; i++) { 
       this.copy = StackManager.stack.pop(); // pop the top of the stack 
       System.out.println("Consumer thread [TID=" + this.iTID + "] pops character =" + this.copy); 
      } 
      System.out.println("Consumer thread [TID=" + this.iTID + "] terminates."); 
     } catch (Exception e) { 
      allException(e); 
      System.exit(1); 
     } finally { 
      this.semaphore.Signal(); // end the critical section 

     } 
    } 
} 

EDIT 3:

class StackManager { 
    // The Stack 
    public static CharStack stack = new CharStack(); 
    private static final int NUM_ACQREL = 4; // Number of Producer/Consumer threads 
    private static final int NUM_PROBERS = 1; // Number of threads dumping stack 
    public static int iThreadSteps = 3; // Number of steps they take 
    // Semaphore declarations. Insert your code in the following: 
    static Semaphore lock = new Semaphore(-1); // create semaphore 
    Consumer consumerSemaphore = new Consumer(lock); 
    Producer producerSemaphore = new Producer(lock); 
    CharStackProber stackProberSemaphore = new CharStackProber(lock); 
    // The main 


    public static void main(String[] argv) 
    { 
     // Some initial stats... 
     try 
     { 
      System.out.println("Main thread starts executing."); 
      System.out.println("Initial value of top = " + stack.getTop() + "."); 
      System.out.println("Initial value of stack top = " + stack.pick() + "."); 
      System.out.println("Main thread will now fork several threads."); 
     } 
     catch(CharStackEmptyException e) 
     { 
      System.out.println("Caught exception: StackCharEmptyException"); 
      System.out.println("Message : " + e.getMessage()); 
      System.out.println("Stack Trace : "); 
      e.printStackTrace(); 
     } 
        /* 
        * The birth of threads 
        */ 


     Consumer ab1 = new Consumer(); 
     Consumer ab2 = new Consumer(); 
     System.out.println ("Two Consumer threads have been created."); 
     Producer rb1 = new Producer(); 
     Producer rb2 = new Producer(); 
     System.out.println ("Two Producer threads have been created."); 
     CharStackProber csp = new CharStackProber(); 
     System.out.println ("One CharStackProber thread has been created."); 
        /* 
       * start executing 
        */ 
     ab1.start(); 
     rb1.start(); 
     ab2.start(); 
     rb2.start(); 
     csp.start(); 
       /* 
        * Wait by here for all forked threads to die 
       */ 
     try 
     { 
      ab1.join(); 
      ab2.join(); 
      rb1.join(); 
      rb2.join(); 
      csp.join(); 
      // Some final stats after all the child threads terminated... 
      System.out.println("System terminates normally."); 
      System.out.println("Final value of top = " + stack.getTop() + "."); 
      System.out.println("Final value of stack top = " + stack.pick() + "."); 
      System.out.println("Final value of stack top-1 = " + stack.getAt(stack.getTop() - 1) + "."); 
      System.out.println("Stack access count = " + stack.getAccessCounter()); 
     } 
     catch(InterruptedException e) 
     { 
      System.out.println("Caught InterruptedException: " + e.getMessage()); 
      System.exit(1); 
     } 
     catch(Exception e) 
     { 
      System.out.println("Caught exception: " + e.getClass().getName()); 
      System.out.println("Message : " + e.getMessage()); 
      System.out.println("Stack Trace : "); 
      e.printStackTrace(); 
     } 
    } 
} 

スタックトレースは以下の通りである:これは短いポスト維持のために

Main thread starts executing. 
Initial value of top = 3. 
Initial value of stack top = d. 
Main thread will now fork several threads. 
Two Consumer threads have been created. 
Two Producer threads have been created. 
One CharStackProber thread has been created. 
Caught exception : java.lang.NullPointerException 
Caught exception : java.lang.NullPointerException 
Message   : null 
Caught exception : java.lang.NullPointerException 
Caught exception : java.lang.NullPointerException 
Caught exception : java.lang.NullPointerException 
Message   : null 
Stack Trace  : 
Stack Trace  : 
Message   : null 
Stack Trace  : 
Message   : null 
Stack Trace  : 
Message   : null 
Stack Trace  : 
java.lang.NullPointerException 
    at Producer.run(Producer.java:18) 
java.lang.NullPointerException 
    at CharStackProber.run(CharStackProber.java:18) 
java.lang.NullPointerException 
    at Consumer.run(Consumer.java:19) 
java.lang.NullPointerException 
    at Consumer.run(Consumer.java:19) 

、I CharStackProberクラスはProducerのコピーであるため、run()メソッドはまったく同じですが内部はF forループStackManager.stack

+0

NPEを取得すると、スタックトレースが取得され、質問に追加し、どのラインをトリガーするかを表示します。 – alfasin

+1

多くの質問があります...あなたのコードは何をしていますか? 'セマフォ'クラスとは何ですか? 「消費者」のコードはどこですか?シンプルなロックの代わりにセマフォを使うのはなぜですか? 'wait()'を呼び出すのは何ですか? 'Signal()'とは何ですか?どこでNPEを取得していますか?スタックトレースはどこですか?実際の調査やデバッグはまだ完了していますか? – shmosel

+0

@alfasin「this.semaphore.wait()」のエラーが表示されます – PatrickVNB

答えて

0

一つのエラーの要素をプリントアウトするだけであることは、あなたが呼んでいるということです。

this.semaphore.wait() 

の代わり:

this.semaphore.Wait() . // (with capital 'W') 

第二に、持っています

Consumer ab1 = new Consumer(); 
    Consumer ab2 = new Consumer(); 
    System.out.println ("Two Consumer threads have been created."); 
    Producer rb1 = new Producer(); 
    Producer rb2 = new Producer(); 

ロックを渡すことなくコンシューマとプロデューサを作成していますが、 NPE

+0

ありがとう!私のスタックはStack S =([a]、[a]、[a]、[a]、[$]、[$]、[$]、[上の初期値が 'd'であっても正しく 'd'に戻るはずです(最初のstacktraceで見られるように、 "スタックトップの初期値=" $ "、" $ " d。 " – PatrickVNB

関連する問題