资源描述
北京理工大学珠海学院课程设计
ZHUHAI CAMPAUS OF BEIJING INSTITUTE OF TECHNOLOGY
班级 09级三班 学号 090202031009 姓名刘宏吉 指导教师 王震 成绩
实验题目 信号量控制线程同步 实验时间 2011年12月2日
设计内容:
程序1:
1. 两个线程,一者输出1-30的偶数,一者输出1-30的奇数。
2. 使用一个信号量,控制二线程分别输出(即一个线程完成数据输出后,另一个线程方可开始数据输出。)
3. 使用二个信号量,控制二线程其中之一输出一个数后,随后另一个线程也输出一个数,交替输出直至结束。
程序2:(教材P98页51题)
假设一个大学为了卖弄其政治上的正确性,准备把美国最高法院的信条“平等但隔离其本身就是不平等”既运用在种族上也运用在性别上,从而结束校园内长期使用的浴室按性别隔离的做法。但是,为了迁就传统习惯,学校颁布法令:当有一个女生在浴室里,那么其他女生可以进入,但是男生不行,反之亦然。在每个浴室的门上有一个滑动指示符号,表示当前处于以下三种可能状态之一:
l 空
l 有女生
l 有男生
用你偏好的程序设计语言编写下面过程(可以随意采用所希望的计数器和同步技术):
l woman_wants_to_enter
l man_wants_to_enter
l woman_leaves
l man_leaves
设计要点与关键技术:
1. 线程的同步与互斥
2. 信号量上的P、V操作算法
3. 使用Visual Studio2008开发平台
信号量控制线程同步该任务含两个程序的设计与编写,程序1同步两个线程,其一输出奇数,另一线程输出偶数,且二者交叉数据输出;本程序采用了C++语言完成,需要涉及到函数主要有3个。程序2实现男女共用浴室的情况下的同步与互斥,男女到达浴室的时间数据放在文本文件。对于给定的输入文件,观察测试输出结果的正确性。本程序采用了C++语言完成,需要设计到函数主要有3个。
关键词:奇数 偶数 同步 互斥 信号量
1.程序流程图
开始
1.1 程序1流程图
i<30
输出偶数
输出奇数
Y
结束
N
否
是
否
是
结束
男的进入浴室
女的进入浴室
浴室是否有男的?
开始
浴室是否为空?
2.1 程序2流程图
2.代码设计
2.1 程序1
2.1.1 控制线程输出地信号量类
Semaphore.java:
package winds.synchronous;
/**
* 定义信号量的操作
* @author Administrator
*
*/
public class Semaphore{
private int semValue;
public Semaphore(int semValue){
this.semValue = semValue;
}
/**
* P操作,信号量减一
*/
public synchronized void p(){
semValue--;
if(semValue<0){
try{
this.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
/**
* V操作,信号量加一
*/
public synchronized void v(){
semValue++;
if(semValue>=0){
this.notifyAll();
}
}
public int getSemValue(){
return semValue;
}
}
2.1.2 交叉打印1-30的奇数和偶数
package winds.synchronous;
/**
* 交叉打印1-30的奇数和偶数
* @author chenmo
*
*/
public class Synchronous {
Semaphore sem1;
Semaphore sem2;
public Synchronous(Semaphore sem1,Semaphore sem2){
this.sem1=sem1;
this.sem2=sem2;
}
public static void main(String[] args){
Semaphore sem1=new Semaphore(1);
Semaphore sem2 =new Semaphore(0);
Synchronous synchronous =new Synchronous(sem1,sem2);
Thread th1= synchronous.new Thread1();
Thread th2 = synchronous.new Thread2();
th1.start();
th2.start();
}
//打印1-30的奇数线程类
class Thread1 extends Thread{
public void run() {
sem1.p();
for(int i=1;i<=30;i++){
if(i % 2 !=0){
System.out.print(i+" ");
sem2.v();
if(i<30){
sem1.p();
}
}
try {
this.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//打印1-30偶数线程类
class Thread2 extends Thread{
public void run() {
sem2.p();
for(int i=1;i<=30;i++){
if(i % 2 ==0){
System.out.print(i+" ");
sem1.v();
if(i<30){
sem2.p();
}
}
try {
this.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
2.2 程序2
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Bath {
/**
* 表示澡堂的状态
* 0 无人在用
* 1 男人在用
* -1 女人再用
*/
private int bathState=0;
/**
* 澡堂当前男人的数量
*/
private int manCount=0;
/**
* 澡堂当前女人的数量
*/
private int womanCount=0;
public static void main(String[] args) {
Bath bath =new Bath();
ExecutorService exc =Executors.newCachedThreadPool(); //线程池
Random r=new Random();
//随机生成男或者女线程,偶数为女,奇数为男
while(true){
int human =r.nextInt(10);
if(human % 2==0)
exc.execute(bath.new Woman());
else
exc.execute(bath.new Man());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
* 代表男人的线程类
* @author chenmo
*
*/
class Man implements Runnable{
public void run() {
man_wants_enter();
go_to_sleep();
man_wants_leaves();
}
//男人进入澡堂
public synchronized void man_wants_enter(){
if(bathState==0){ //如果澡堂的状态是无人在用,则正常进入,并且把澡堂状态变为男人在用
manCount++;
bathState=1;
}else if(bathState==1){ //如果当前澡堂状态是男人在用,则直接进入
manCount++;
}else {
try {
//澡堂被女人占用,则当前线程等待
wait();
manCount++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(manCount+" man having a bath.");
}
public synchronized void man_wants_leaves(){
manCount--;
System.out.println(manCount+" man remain.");
//当澡堂的男人全部出来之后,唤醒等待的女人线程,并设置当前澡堂状态为无人在用
if(manCount==0){
bathState=0;
notify();
}
}
}
/**
* 代表女人的线程类
* @author chenmo
*
*/
class Woman implements Runnable{
public void run() {
woman_wants_enter();
go_to_sleep();
woman_wants_leaves();
}
public synchronized void woman_wants_enter(){
if(bathState==0){
//澡堂没人,正常进入
womanCount++;
bathState=-1;//澡堂状态变为女人在用
}else if(bathState==-1){ //澡堂已经有女人在用,直接进入
womanCount++;
}else{
try {
//澡堂被男人占用,当前线程等待
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
womanCount++;
}
System.out.println(womanCount+" woman having bath.");
}
public synchronized void woman_wants_leaves(){
womanCount--;
System.out.println(womanCount+" woman remain.");
if(womanCount==0) { //澡堂的女人全部出来之后,澡堂状态变为无人在用,并唤醒正在等待的男人线程
bathState=0;
notify();
}
}
}
//让线程随机睡眠一段时间,代表的是洗澡时间
public static void go_to_sleep(){
try{
Thread.sleep((long)(Math.random()*3000));
}catch(Exception e){
e.printStackTrace();
}
}
}
3.运行结果
3.1程序交叉打印1-30的奇数和偶数运行结果
3.2程序澡堂管理运行结果
展开阅读全文