簡體   English   中英

使用信號量監視程序在java中無法正常工作

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

我試圖在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.另一方面,當生產者延遲更大時,當資源變為0時,程序似乎陷入死鎖(而我希望消費者線程暫停,直到資源線程產生一些東西)

示例輸出:

當消費者延遲較低時:

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

當生產者延遲較低時:

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

程序有什么問題?

首先,創建一個信號量與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();
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM