使用信号量的监控程序在 java 中无法按预期工作
Monitor program using semaphore does not work as expected in java
我正在尝试在 java 中创建一个多生产者多消费者问题的解决方案(即监视器)。
我决定使用 Semaphore class 并同步如下。
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 个初始许可的信号量,如 here 所述。这不是上限,所以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();
}
}
我正在尝试在 java 中创建一个多生产者多消费者问题的解决方案(即监视器)。
我决定使用 Semaphore class 并同步如下。
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 个初始许可的信号量,如 here 所述。这不是上限,所以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();
}
}