2.三个进程P1、P2、P3使用包含N个单元的缓冲区,P1每次用Produce()生成一个正整数并用put()送入缓冲区的某个空单元;P2每次用getodd()从该缓冲区中取出一个奇数并用countodd()统计奇数个数;P3每次用geteven()从缓冲区中取出偶数并用counteven()统计偶数个数,请用信号量实现三个进程的同步与互斥活动。用java 语言写
时间: 2024-03-16 22:41:53 浏览: 23
以下是Java语言的解决方案,使用了Java的内置信号量Semaphore:
```java
import java.util.concurrent.Semaphore;
public class ProducerConsumer {
private static final int N = 100; //缓冲区大小
private static int[] buffer = new int[N]; //缓冲区
private static int in = 0, out = 0; //缓冲区的写入和读取指针
private static Semaphore empty = new Semaphore(N); //空单元数量
private static Semaphore full = new Semaphore(0); //已有数据的单元数量
private static Semaphore mutex = new Semaphore(1); //互斥访问信号量
public static void main(String[] args) {
Thread p1 = new Thread(new Producer());
Thread p2 = new Thread(new OddConsumer());
Thread p3 = new Thread(new EvenConsumer());
p1.start();
p2.start();
p3.start();
}
static class Producer implements Runnable {
public void run() {
try {
while (true) {
int item = produce();
put(item);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private int produce() {
return (int) (Math.random() * 100); //生成随机数
}
private void put(int item) throws InterruptedException {
empty.acquire(); //等待空单元
mutex.acquire(); //获取互斥访问权
buffer[in] = item; //将数据写入缓冲区
in = (in + 1) % N; //更新写入指针
mutex.release(); //释放互斥访问权
full.release(); //通知已有数据的单元数量+1
}
}
static class OddConsumer implements Runnable {
public void run() {
try {
while (true) {
int item = getodd();
int count = countodd();
System.out.println("Odd count: " + count + ", item: " + item);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private int getodd() throws InterruptedException {
int item;
full.acquire(); //等待有奇数
mutex.acquire(); //获取互斥访问权
int i = out;
while (buffer[i] % 2 == 0) { //查找奇数
i = (i + 1) % N;
}
item = buffer[i]; //取出奇数
out = (i + 1) % N; //更新读取指针
mutex.release(); //释放互斥访问权
empty.release(); //通知空单元数量+1
return item;
}
private int countodd() throws InterruptedException {
int count = 0;
mutex.acquire(); //获取互斥访问权
int i = out;
for (int j = 0; j < full.availablePermits(); j++) { //遍历已有数据的单元
if (buffer[i] % 2 == 1) { //统计奇数个数
count++;
}
i = (i + 1) % N;
}
mutex.release(); //释放互斥访问权
return count;
}
}
static class EvenConsumer implements Runnable {
public void run() {
try {
while (true) {
int item = geteven();
int count = counteven();
System.out.println("Even count: " + count + ", item: " + item);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private int geteven() throws InterruptedException {
int item;
full.acquire(); //等待有偶数
mutex.acquire(); //获取互斥访问权
int i = out;
while (buffer[i] % 2 == 1) { //查找偶数
i = (i + 1) % N;
}
item = buffer[i]; //取出偶数
out = (i + 1) % N; //更新读取指针
mutex.release(); //释放互斥访问权
empty.release(); //通知空单元数量+1
return item;
}
private int counteven() throws InterruptedException {
int count = 0;
mutex.acquire(); //获取互斥访问权
int i = out;
for (int j = 0; j < full.availablePermits(); j++) { //遍历已有数据的单元
if (buffer[i] % 2 == 0) { //统计偶数个数
count++;
}
i = (i + 1) % N;
}
mutex.release(); //释放互斥访问权
return count;
}
}
}
```
在Produce函数中,先生成随机数,然后等待空单元,获取互斥访问权,将数据写入缓冲区,更新写入指针,释放互斥访问权,最后通知已有数据的单元数量+1。
在OddConsumer和EvenConsumer函数中,先等待有奇数或偶数,然后获取互斥访问权,查找奇数或偶数,取出数据,更新读取指针,释放互斥访问权,最后通知空单元数量+1。同时,统计奇数或偶数个数时,需要遍历已有数据的单元,获取互斥访问权,释放互斥访问权。