简体   繁体   English

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

[英]Monitor program using semaphore does not work as expected in java

I am trying to create a multiple producer multiple consumer problem's solution(ie a Monitor) in java. 我试图在java中创建一个多生产者多个消费者问题的解决方案(即监视器)。

I decided to use Semaphore class and synchronized as follows. 我决定使用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();
        }
    }
}

But the output is not as expected. 但输出并不像预期的那样。 When producer delay is less than consumer delay, the no of resources available with semaphore go above 10. On the other hand, when producer delay is greater, the program seemingly goes into a deadlock when resource become 0 (while I expect consumer thread to pause, until resource thread produces something) 当生产者延迟小于消费者延迟时,信号量可用资源的数量超过10.另一方面,当生产者延迟更大时,当资源变为0时,程序似乎陷入死锁(而我希望消费者线程暂停,直到资源线程产生一些东西)

Example output: 示例输出:

when consumer delay is lower: 当消费者延迟较低时:

consumed:       Available now:  10
consumed:       Available now:  10
produced:       Available now:  11
produced:       Available now:  10
consumed:       Available now:  8
consumed:       Available now:  8
produced:       Available now:  10
produced:       Available now:  10
consumed:       Available now:  9
consumed:       Available now:  8
produced:       Available now:  9
consumed:       Available now:  8
produced:       Available now:  9
consumed:       Available now:  8
consumed:       Available now:  7
consumed:       Available now:  6
produced:       Available now:  7
produced:       Available now:  8
consumed:       Available now:  7
consumed:       Available now:  6
produced:       Available now:  7
produced:       Available now:  8
consumed:       Available now:  7
consumed:       Available now:  6
consumed:       Available now:  5
consumed:       Available now:  4
produced:       Available now:  5
produced:       Available now:  6
consumed:       Available now:  5
consumed:       Available now:  4
produced:       Available now:  5
produced:       Available now:  6
consumed:       Available now:  5
consumed:       Available now:  4
consumed:       Available now:  3
consumed:       Available now:  2
produced:       Available now:  3
produced:       Available now:  4
consumed:       Available now:  3
consumed:       Available now:  2
produced:       Available now:  3
produced:       Available now:  4
consumed:       Available now:  3
consumed:       Available now:  2
consumed:       Available now:  0
consumed:       Available now:  0
produced:       Available now:  2
produced:       Available now:  2
consumed:       Available now:  1
consumed:       Available now:  0
produced:       Available now:  1
produced:       Available now:  2
consumed:       Available now:  1
consumed:       Available now:  0

when producer delay is lower: 当生产者延迟较低时:

produced:       Available now:  11
consumed:       Available now:  10
produced:       Available now:  11
consumed:       Available now:  10
produced:       Available now:  11
produced:       Available now:  12
consumed:       Available now:  11
consumed:       Available now:  10
produced:       Available now:  11
produced:       Available now:  12
produced:       Available now:  13
produced:       Available now:  12
consumed:       Available now:  12
consumed:       Available now:  11
produced:       Available now:  13
produced:       Available now:  14
consumed:       Available now:  13
consumed:       Available now:  12
produced:       Available now:  13
produced:       Available now:  14
produced:       Available now:  15
produced:       Available now:  16
consumed:       Available now:  15
consumed:       Available now:  14
produced:       Available now:  15
produced:       Available now:  16
consumed:       Available now:  15
consumed:       Available now:  14
produced:       Available now:  15
produced:       Available now:  16
produced:       Available now:  17
consumed:       Available now:  16
consumed:       Available now:  17
produced:       Available now:  18
produced:       Available now:  17
produced:       Available now:  18
consumed:       Available now:  17
consumed:       Available now:  16
produced:       Available now:  17
produced:       Available now:  18
consumed:       Available now:  16
consumed:       Available now:  17
produced:       Available now:  17
produced:       Available now:  18
produced:       Available now:  19
produced:       Available now:  20
consumed:       Available now:  19
consumed:       Available now:  18
produced:       Available now:  19
produced:       Available now:  20
consumed:       Available now:  18
produced:       Available now:  19
consumed:       Available now:  18
produced:       Available now:  20
produced:       Available now:  21
produced:       Available now:  22
consumed:       Available now:  21
consumed:       Available now:  20
produced:       Available now:  21
produced:       Available now:  22
consumed:       Available now:  21
consumed:       Available now:  20
produced:       Available now:  21
produced:       Available now:  22
produced:       Available now:  23
produced:       Available now:  24
consumed:       Available now:  23
consumed:       Available now:  22
produced:       Available now:  23
produced:       Available now:  24

What is wrong in the program? 程序有什么问题?

First, you create a Semaphore with 10 initial permits, as explained here . 首先,创建一个信号量与10个初始许可,如解释在这里 It is not an upper limit, so release() can make the number of available permits go above 10. 它不是上限,因此release()可以使可用许可数超过10。

Also, look at the code below: 另外,请看下面的代码:

synchronized (this.lock) {
    s.acquire(); // consume resource
}

You acquire the lock. 你获得了锁。 If there are no resources available, the thread pauses, but does not release the lock. 如果没有可用资源,则线程暂停,但不释放锁。 Thus, the below code cannot acquire the lock and cannot execute. 因此,下面的代码无法获取锁并且无法执行。 Consumer waits for a permit and producer waits for the lock, resulting in a deadlock. 消费者等待许可证,生产者等待锁定,导致死锁。

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

You can solve this problem by not synchronizing s.acquire() and s.release() . 您可以通过不同步s.acquire()s.release()来解决此问题。

This is what will happen 这就是将要发生的事情

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM