中 北 大 学 软 件 学 院
实 验 报 告
专 业:
软件工程
方 向:
智慧城市
课程名称:
操作系统
班 级:
15140Z01
学 号:
1514010739
姓 名:
杨亮
辅导教师:
2016 年 3 月 制
成 绩 :
实 验 时 间 2017 年 11 月 4 日 14 时
学 时 数
4
至 17 时
实 验 名 称
2 . 实 验 目 的
进程同步控制
(1)加强对进程概念的理解,尤其是对进程的同步与互斥机制的理解。
(2)分析进程竞争资源的现象,学习解决进程互斥与同步的方法。
3. 实 验 内 容
编程模拟实现生产者-消费者进程。
测试类 TestClient .Java
//消费者线程 Consumer .Java
//生产者线程
Producer .Java
4. 实 验 原 理 或 流 程 图
生产者-消费者问题描述的是:有一群生产者进程在生产产品,并将这些产品提供给消
费者进程去消费。为使生产者进程与消费者进程能够并发执行,在两者之间设置了一个具有
n 个缓冲区的缓冲池,生产者进程将它所生产的产品放入一个缓冲区中;消费者进程可以从
一个缓冲区中取走产品去消费。尽管所有的生产者和消费者进程都是以异步方式运行的,但
它们之间必须保持同步,即不允许消费者进程到一个空缓冲区去取产品;也不允许生产者进
程向一个已经装满产品的缓冲区中投放产品。
这是一个同步与互斥共存的问题。
生产者—消费者问题是一个同步问题。即生产者和消费者之间满足如下条件:
(1) 消费者想接收数据时,有界缓冲区中至少有一个单元是满的。
(2) 生产者想发送数据时,有界缓冲区中至少有一个单元是空的。
故设置两个信号量:
(1) empty:说明空缓冲区的数目,初值为有界缓冲区的大小 N。
(2) full:说明已用缓冲区的数目,初值为0。
由于有界缓冲区是临界资源,因此,各生产者进程和各消费者进程之间必须互斥执行。
故设置一个互斥信号量 mutex,其初值为1。
5. 实 验 过 程 或 源 代 码
//测试类
package com;
public class TestClient {
TestClient .Java
public static void main(String[] args) {
String lock = new String(""); // 创建对象锁
P p = new P(lock);
C r = new C(lock);
ThreadP pThread = new ThreadP(p);
ThreadC cThread = new ThreadC(r);
pThread.start();
cThread.start();
}
}
//缓冲池
class ValueObject {
public static int size = 10;
}
//生产者线程
package com;
Producer .Java
import java.util.Random;
public class Producer extends Thread{
private P p;
public Producer(P p){
this.p = p;
}
public void run(){
//生产者不停的向缓冲池中存放数据
while(true){
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
p.setValue();
}
}
}
class P {
private String lock;
public P(String lock){
this.lock = lock;
}
public void setValue(){
Random random = new Random();
try{
synchronized (lock) {
//如果不为空,生产者处于等待状态
if(!(ValueObject.size == 0)){
待这个池没有数据被消费者用,它用完之后,我就放新的数据 ");
System.out.println("我是生产者,此时缓冲池中有数据,我正在等
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.wait();
}else{
ValueObject.size = random.nextInt(20); //随机产生 0 到 20
的数 存入缓冲池中
}
lock.notify();
}
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
//消费者线程 Consumer .Java
package com;
public class Consumer extends Thread{
private C c;
public Consumer(C c){
this.c = c;
}
public void run(){
/**
* 消费者不停的从缓冲池中取数据
*/
while(true){
c.getValue();
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class C {
private String lock;
public C(String lock){
this.lock = lock;
}
public void getValue(){
try{
synchronized (lock) {
//当没有值可供消费者使用时,使用消费者的线程处于等待状态
if(ValueObject.size==0){
System.out.println("我是消费者,我要产品:");
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.wait();
}else{
System.out.println("消费者获取到的值
是:"+ValueObject.size);
ValueObject.size--; //消费者取值之后,将当前值减一
}
lock.notify();
//唤醒生产者可以向缓冲池中存放数据了
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
6. 实 验 结 论 及 心 得