Java 在正在运行的类中将信号量初始化为null

Java 在正在运行的类中将信号量初始化为null,java,mutex,semaphore,Java,Mutex,Semaphore,我试图用0和1设置一个简单的信号量,其中wait()函数和Signal()函数只允许临界部分中的线程 public class Producer extends BaseThread { Semaphore semaphore = null; private char block; // block to be returned public Producer(Semaphore x) { this.semaphore = x; }

我试图用0和1设置一个简单的信号量,其中wait()函数和Signal()函数只允许临界部分中的线程

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()

现在的问题是,在运行代码时,我不断遇到消费者类和生产者类的NullPointerException错误,我似乎找不到答案。我错过了什么

编辑: 代码应该推送StackManager.stack顶部的下一个char值,但是由于还有另一个名为Consumer的类也执行同样多的pop()操作,因此它们需要执行synchronized。我只能使用信号量,这是我创建的类:

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();
    }
}
请注意,信号量在main()中初始化为-1,因为由于本课程的复杂性,我们需要创建一个信号量类,其中at-1表示准备好下一个线程,0表示某个线程处于其关键部分。这意味着我写的wait()方法是递增和信号递减

编辑2:添加了消费者类

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

        }
    }
}
stacktrace如下所示:

    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)

为了缩短这篇文章的篇幅,我省略了CharStackProber类,因为它只是Producer的一个副本,其中run()方法完全相同,但For循环的内部仅用于打印StackManager的元素。stack

一个错误是您调用:

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

您得到NPE,这意味着您也会得到stacktrace,将其添加到您的问题中,并向我们显示哪一行触发它。这么多问题。。。你的代码应该做什么?这是什么信号量类?消费者的代码在哪里?为什么使用信号量而不是简单的锁?你知道调用
wait()
做什么吗?
Signal()
应该做什么?你在哪里得到NPE?堆栈跟踪在哪里?你做过任何实际的研究或调试了吗?@alfasin我在“this.semaphore.wait()”一行上得到了错误。看shmosel的评论,你应该提供更多details@alfasin我对我的文章进行了更详细的编辑。对不起,我是StackOverflow的新手谢谢!这些行修复了我的NPE:)现在的问题是,我的堆栈打印为堆栈S=([a]、[a]、[a]、[a]、[a]、[a]、[$]、[$]、[$]、[$]、[$]、[$]、[$]、[$]),即使顶部的初始值是“d”,也应该正确地返回为“d”(正如您在堆栈跟踪的开头所看到的,“堆栈顶部的初始值=d”)
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();