在讲解PV操作之前,需要先明白PV操作用来解决什么问题?
PV操作用以解决进程间的互斥问题
eg:火车售票问题 。以下就会出现BUG,假设当 x = 1时,如果
p1 , p2 , 同时执行,那么相当于票数为1的这张票售卖两次,这显然是不能出现的错误。
cobegin // 表示p1 , p2 同时执行
int x = 7 ; // 假设 x 为北京到上海的机票,还剩下7张
void p1(){
if(x>0) x = x - 1 ; cout << "买票成功" << endl ;
else cout << "票已售完" << endl ;
}
void p2(){
if(x>0) x = x - 1 ; cout << "买票成功" << endl ;
else cout << "票已售完" << endl ;
}
coend
那么如何解决???
其实很简单,只需要让p1执行的时候,p2不要执行。p2执行的时候,p1不要执行。此时就需要对该程序PV操作。参考代码如下:
Semapohore s = 1 ; // s 为信号量,用于实现互斥操作。也是对临界资源的设定。
int x = 7 ; // 假设 x 为北京到上海的机票,还剩下7张
cobegin // 表示p1 , p2 同时执行
void p1(){
p(s) ; // 把信号量s锁住,让p2不能执行,s -- ;如果s <= 0 , 则进入等待无法向下继续执行
if(x>0) x = x - 1 ; cout << "买票成功" << endl ;
else cout << "票已售完" << endl ;
v(s) ; // 把信号量s锁住,让p1可以执行,s ++
}
void p2(){
p(s) ;
if(x>0) x = x - 1 ; cout << "买票成功" << endl ;
else cout << "票已售完" << endl ;
v(s) ;
}
coend
经典进程问题:生产者 消费者问题
1:一个生产者与一个消费者共同使用一个缓冲区 且只能放进一件产品
Semaphore s = 1 ; // 代表缓冲区能否放进产品
Semaphore t = 0 ; // 代表缓冲区能否取出产品
cobegin
void prudece(){
p(s) ; // 把缓冲区锁住,无法放进产品
生产产品并且放进缓冲区
v(t) ; // 缓冲区中可以取出产品
}
void consumer(){
p(t) ;
从缓冲区取出产品
v(s) ; // 释放缓冲区。
}
2:一个生产者与一个消费者共同使用一个缓冲区 且能放进n件产品(n>1);
(与第一个不同的是,缓冲区中不止一件产品)
Semaphore s = 1 ; // 代表缓冲区能否放进产品 , s = 1 表示能放进
Semaphore t = 0 ; // 代表缓冲区能否取出产品 , t = 0 表示无法取出
int b[n] ; // 缓冲区的每一个位置是否有产品存放
int w1 = 0 , w2 = 0 ; // 代表产品以及存放到的位置 和 产品应该要取出来的位置。
cobegin
void prudece(){
p(s) ; // 把缓冲区锁住,无法放进产品
生产产品并且放进缓冲区
b[w1] = 1 ; // 表示 w1 这个位置 已经放进产品
w1 = (w1 + 1) % n ; // 下次放进产品则需要在下一个位置
v(t) ; // 缓冲区中可以取出产品
}
void consumer(){
p(t) ;
从缓冲区w2取出产品
w2 = (w2 + 1) % n ;
v(s) ; // 释放缓冲区。
}
3:多个生产者与多个消费者共同使用一个缓冲区 且能放进n件产品(n>1);(与第二个不同的是,有多个生产者可以共同生产,但是不能同时放进缓冲区;有多个消费者可以共同消费,但是不能同时从缓冲区取出产品)
思路:
1 : 设置三个信号量 。
(1):s = 1 , 表示缓冲区可以使用
(2) : empty = n , 表示缓冲区中空的数量(即表示可以放进产品的数量)
(3) : full = 0 ; 表示缓冲区已经放进产品的数量
2 : 设置 w1 , w2 两个值,分别表示从缓冲区w1值放进产品 , 从缓冲区w2值取出产品
3 : s 作为互斥信号使用
代码如下:
Semaphore s = 1 , empty = n , full = 0 ;
int w1 = 0 , w2 = 0 ;
int b[n] ;
cobegin
void pruduct(){
p(s) ;
p(empty) ;
b[w1] = 1 ; // 在w1放进产品 , 用1表示(注:只是为了表示简单)
w1 = (w1 + 1) % n ;
v(s) ;
v(full) ;
}
void consume(){
p(s) ;
p(full) ;
b[w2] = 0 ;
w2 = (w2 + 1) % n ;
v(s) ;
v(empty) ;
}