使用信号量的监控程序在java中无法正常工作

使用信号量的监控程序在java中无法正常工作,java,multithreading,semaphore,synchronized,producer-consumer,Java,Multithreading,Semaphore,Synchronized,Producer Consumer,我试图用java创建一个多生产者多消费者问题的解决方案(即监视器) 我决定使用Semaphore类并按如下方式进行同步 import java.util.concurrent.Semaphore; public class PC implements Runnable { Semaphore s; Object lock; boolean isProducer; final int ProcessCount = 4; final int producer

我试图用java创建一个多生产者多消费者问题的解决方案(即监视器)

我决定使用Semaphore类并按如下方式进行同步

import java.util.concurrent.Semaphore;

public class PC implements Runnable {
    Semaphore s;
    Object lock;
    boolean isProducer;
    final int ProcessCount = 4;
    final int producerDelay = 1500;
    final int consumerDelay = 1000;

    public static void main(String[] args) {
        new PC();
    }

    PC() {
        this.s = new Semaphore(10);
        this.lock = new Object();
        this.isProducer = true;
        // create few consumers and producers
        for (int i = 0; i < ProcessCount; i++) {
            new Thread(this).start();
        }
    }

    public void run() {    //alternately create producers and consumers
        if (isProducer) {
            isProducer = false;
            producer();
        } else {
            isProducer = true;
            consumer();
        }
    }

    void producer() {
        try {
            while (true) {
                synchronized (this.lock) {
                    s.release(); // produce an resource
                }
                System.out.println("produced:\tAvailable now:\t" + s.availablePermits());
                Thread.sleep(producerDelay);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    void consumer() {
        try {
            while (true) {
                synchronized (this.lock) {
                    s.acquire(); // consume resource
                }
                System.out.println("consumed:\tAvailable now:\t" + s.availablePermits());
                Thread.sleep(consumerDelay);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
当生产者延迟较低时:


程序中出了什么问题?

首先,创建一个带有10个初始许可证的信号量,如前所述。它不是上限,因此
release()
可以使可用许可证的数量超过10个

另外,请查看下面的代码:

synchronized (this.lock) {
    s.acquire(); // consume resource
}
你得到了锁。如果没有可用的资源,线程将暂停,但不会释放锁。因此,下面的代码无法获取锁并且无法执行。使用者等待许可证,生产者等待锁,导致死锁

synchronized (this.lock) {
    s.release(); // produce an resource
}

您可以通过不同步
s.acquire()
s.release()
来解决此问题。首先,创建一个具有10个初始许可证的信号量,如前所述。它不是上限,因此
release()
可以使可用许可证的数量超过10个

另外,请查看下面的代码:

synchronized (this.lock) {
    s.acquire(); // consume resource
}
你得到了锁。如果没有可用的资源,线程将暂停,但不会释放锁。因此,下面的代码无法获取锁并且无法执行。使用者等待许可证,生产者等待锁,导致死锁

synchronized (this.lock) {
    s.release(); // produce an resource
}

您可以通过不同步
s.acquire()
s.release()
来解决此问题,这就是将要发生的情况

    void producer() {
        try {
            while (true) {

                //***All producers are stuck here because "first consumer" is having the lock.
                synchronized (this.lock) {
                    s.release(); // produce an resource
                }
                System.out.println("produced:\tAvailable now:\t" + s.availablePermits());
                Thread.sleep(producerDelay);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    void consumer() {
        try {
            while (true) {
                //***All other consumers are stuck here because of line below.
                synchronized (this.lock) {
                    //***"First consumer" is stuck here waiting s.release()
                    s.acquire(); // consume resource
                }
                System.out.println("consumed:\tAvailable now:\t" + s.availablePermits());
                Thread.sleep(consumerDelay);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

这就是将要发生的事情

    void producer() {
        try {
            while (true) {

                //***All producers are stuck here because "first consumer" is having the lock.
                synchronized (this.lock) {
                    s.release(); // produce an resource
                }
                System.out.println("produced:\tAvailable now:\t" + s.availablePermits());
                Thread.sleep(producerDelay);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    void consumer() {
        try {
            while (true) {
                //***All other consumers are stuck here because of line below.
                synchronized (this.lock) {
                    //***"First consumer" is stuck here waiting s.release()
                    s.acquire(); // consume resource
                }
                System.out.println("consumed:\tAvailable now:\t" + s.availablePermits());
                Thread.sleep(consumerDelay);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

我不明白为什么你需要
同步的
块来调用你的
信号量
,你能澄清一下吗?@NicolasFilotto我认为信号量不是线程安全的(我猜监视器是线程安全的,而信号量不是线程安全的),这就是我使用锁的原因。我错了吗?是的,你错了,这是我们可以用来创建线程安全类的可用内置工具之一。我不明白为什么需要
同步的
块来调用你的
信号量,你能澄清一下吗?@NicolasFilotto我认为信号量不是线程安全的(我猜监视器是线程安全的,而信号量不是线程安全的),这就是我使用锁的原因。我错了吗?是的,你错了,它是一个可用的内置工具,我们可以使用它创建线程安全的类,信号量线程安全吗?我认为信号量不是线程安全的,而监视器是线程安全的。是的,信号量是线程安全的,不需要同步它们的调用。检查这个:信号量是吗线程安全?我认为信号量不是线程安全的,而监视器是线程安全的。是的,信号量是线程安全的,不需要同步它们的调用。检查此项: