实验目的:
掌握使用信号量解决进程(线程)同步控制问题。
实验内容:
- 说明所选信号量的作用及初始值设置;
- 说明未使用信号量时可能产生的问题及其在代码执行结果上的体现;
- 给出使用信号量控制的程序代码;
- 说明使用信号量控制后的执行结果。
- 补充下列程序,要求y的输出值为50
[1]选用mutex用来控制a进程的不争抢,sx用来控制进程b的执行时机,mutex初始值为1,sx初始值为0
int x = 0,y = 10;
semaphore mutex = 1, sx = 0;
void a(){p(mutex);x++;v(sx);v(mutex);}
void b(){p(sx);p(sx);p(sx);p(sx);p(sx);y = y * x;}
void main(){
cobegin{a();a();a();a();a();b();}
cout<<"y="<<y;
}
结果:
[2]如果未使用信号量可能会造成代码的执行顺序紊乱,达不到想要的执行结果,如图所示,产生了多种执行结果:
[3]使用信号量控制后的程序代码:
int x = 0,y = 10;
semaphore mutex = 1, sx = 0;
void a(){p(mutex);x++;v(sx);v(mutex);}
void b(){p(sx);p(sx);p(sx);p(sx);p(sx);y = y * x;}
void main(){
cobegin{a();a();a();a();a();b();}
cout<<"y="<<y;
}
[4]使用信号量控制之后的执行结果:
- 三个进程P1、P2、P3使用包含N个单元的缓冲区,P1每次用Produce()生成一个正整数并用put()送入缓冲区的某个空单元;P2每次用getodd()从该缓冲区中取出一个奇数并用countodd()统计奇数个数;P3每次用geteven()从缓冲区中取出偶数并用counteven()统计偶数个数,请用信号量实现三个进程的同步与互斥活动。
代码:
int arr[5];
int count = 1;
int countOdd = 0;
int countEven = 0;
semaphore mutex = 1, N = 5;
void put(int x){
int i;
for(i = 0; i<=4; i++){
if(arr[i] == 0){
arr[i] = x;
count++;
return;
}
}
}
void Produce(){
p(N);
put(count);
}
void countodd(){
countOdd++;
v(N);
}
void counteven(){
countEven++;
v(N);
}
void getOdd(){
int i;
for(i = 0; i<5; i++){
if(arr[i]%2 == 1){
arr[i] = 0;
countodd();
return;
}
}
}
void getEven(){
int i;
for(i = 0; i<5; i++){
if(arr[i]%2 == 0 && (arr[i] != 0)){
arr[i] = 0;
counteven();
return;
}
}
}
void P1(){
p(mutex);
Produce();
v(mutex);
}
void P2(){
p(mutex);
getOdd();
v(mutex);
}
void P3(){
p(mutex);
getEven();
v(mutex);
}
void main(){
cobegin{
P1();P1();P1();P1();P1();P2();P3();P2();P3();P2();P3();P2();P3();P2();P3();P2();P3();P2();P3();
}
cout<<"Even numbers:"<<countEven<<",Odd numbers:"<<countOdd;
}
实验结果: