答:为了解决信号量机制编程麻烦,易出错的问题。
之前我们学习了信号量机制,在使用过程中发现了诸多不便。缺点如下:
1.在使用过程中若是PV顺序不当会出现死锁
2.进程对临界资源访问都有自己的临界区,临界区管理不方便。
管程=共享资源+同步操作
1.共享数据结构
2.对数据结构初始化的语句
3.一组用来访问数据结构的过程(函数)
1.封装于管程内部的数据结构仅能被封装于管程内部的过程所访问
2.一个进程只有通过调用管程内的过程才能进入管程访问共享数据
3.管程每次只允许一个进程进入管程执行管程内的过程
1.进程定义的是私有数据结构PCB,管程定义的是公共数据结构
2.进程目的在于实现系统的并发性和占有系统资源;管程的设置是解决共享资源的互斥使用问题。
3.进程是由顺序程序执行有关操作,而管程主要是进行同步操作和初始化操作
4.进程通过调用管程中的过程对共享数据结构实行操作,该剁成就如通常的子程序一样被调用,因而管程是被动工作方式,进程是主动工作方式
5.进程之间能并发执行,而管程不能与其调用者并发
6.进程具有动态性,由“创建”而诞生,由“撤销”而消亡,而管程是操作系统中的一个资源管理模块,供进程调用。
各进程必须互斥访问管程的特性是编译器实现的。可在管程中设置条件变量及等待/唤醒操作以解决同步问题。
java实现
对了,我这题要求生产者和消费者随机访问临界区。
package os;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class No2 {
public static void main(String[] args) {
tube info=new tube();
while(true) {
Random random=new Random();
int flag=random.nextInt(2);
if(flag==1) {
Produce p=new Produce(info);
Thread p1=new Thread(p);
p1.start();
}
else {
Consume q=new Consume(info);
Thread q1=new Thread(q);
q1.start();
}
}
}
}
//管程
//组成:1.共享数据结构2.对数据结构初始化的语句3.一组用来访问数据结构的过程(函数)
class tube{
/*--------------1.共享数据-缓冲池----------------------------------------*/
private final static int N=10;//设置缓冲池的容量为10
private int count;
private Lock lock;
//条件变量
private Condition notfull;
private Condition notempty;
//容量
/*-----------2.多个过程,用来被外部进程调用从而访问共享数据-----------------*/
//生产者将自己生产的产品放入缓冲池中,
//count表示在缓冲池中已有的产品数目,count>=N,生产者等待
void put() {
lock.lock();
while(count>=N) {
try {
System.out.println("缓冲池满了,生产者被阻塞!");
notfull.await();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
count++;
System.out.println("生产者生产了一个产品,缓冲池产品数量为:"+count);
notempty.signal();
lock.unlock();
}
//消费者从缓冲池中取一个产品,当count<=0,消费者应等待
void get() {
lock.lock();
while(count<=0) {
try {
System.out.println("缓冲池是空的,消费者被阻塞!");
notempty.await();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
count--;
System.out.println("消费者消耗了一个产品,缓冲池产品数量为:"+count);
notfull.signal();
lock.unlock();
}
/*--------------3.共享数据的初始化代码--------------------------------------*/
public tube() {
this.count=0;
this.lock=new ReentrantLock();
this.notfull=lock.newCondition();
this.notempty=lock.newCondition();
}
}
//生产者
class Produce implements Runnable{
private tube info;
public Produce(tube info) {
this.info=info;
}
public void run() {
while(true) {
try {
info.put();
Thread.sleep(100);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费者
class Consume implements Runnable{
private tube info;
public Consume(tube info) {
this.info=info;
}
public void run() {
while(true) {
try {
info.get();
Thread.sleep(100);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
结果显示:
无数次,后面就不截图了