从信号量的理论跨越到对其应用解决实际的问题,对于我这种人来说,是一种脱离地心引力飞向太阳系的体验。
以下有7个问题(不写目录了)。
1、
生产者---消费者问题
有一个或多个生产者生产某种类型的数据(记录、字符),并防止在缓冲区中;有一个消费者从缓冲区中取数据,每次取一项;系统保证避免对缓冲区的重复操作,也就是说,在任何时候只有一个主体(生产者或者消费者)可以访问缓冲区。问题是要确保这种情况,当缓冲区已满时,生产者不会继续向其中添加数据;当缓冲区为空时,消费者不会从中移走数据。
1)问题分析:
从题中可以发现需要对缓冲区进行同步互斥操作,生产者为消费者生产必要产品放入缓冲区,消费者为生产者生产空闲缓冲区,这就需要同步操作;对于同一个缓冲区而言,只能有一个生产者或消费者访问,也就是生产者与生产者之间、生产者与消费者、消费者与消费者需要互斥操作。
对于生产者:
判断缓冲区是否为满,如果为满,则等待;否则,允许一个生产者写入。
对于消费者:
判断缓冲区是否为空,如果为空,则等待;否则,允许一个消费者读取。
2)伪码描述:
semaphore buffer, empty, full;//分别表示缓冲,缓冲剩余资源,缓冲已用资源的信号量
buffer.v = 1;//表示缓冲空闲
empty.v = MAX_SIZE;//表示缓冲为空
full.v = 0;//表示缓冲为空
void Producer()
{
while(isProduce()) {
//produce
P(empty);//判断是否有空闲的缓冲
P(buffer);//判断缓冲是否占用
append();//将产品放入缓冲中
V(buffer);//释放对缓冲的使用
V(full);//缓冲中添加一块产品
}
}
void Consumer()
{
while(isConsume()) {
P(full);//判断是否有非空的缓冲
P(buffer);//判断缓冲是否占用
take();//取走产品
V(buffer);//释放对缓冲的使用
V(empty);//多出一块空闲缓冲区
//consume
}
}
2、
哲学家进餐问题
有5位哲学家住在一座房子里,在他们面前有一张餐桌。每位哲学家的生活就是思考和吃饭。所有的哲学家的食物是意大利面条,由于缺乏手工技能,每位哲学家需要两把叉子进餐。一个圆盘上有一大碗面,每位哲学家面前有一个盘子,左手边有一个叉子。每个想吃饭的哲学家将坐到桌子旁分配给他的位置上,使用盘子两侧的叉子,取面和吃面。
1)问题分析:
题中的叉子显然是一个互斥资源,对于一个叉子而言,如果有一个哲学家占用,那么另一个哲学家只能等待。
对于每一个哲学家来说,
他需要判断能否申请到手边的两个叉子,如果只能得到一个或者没有得到叉子,只能等待;否则,可以进餐。
考虑到会出现饥饿的现象,比如:同时拿起左手边的叉子,所有哲学家同时等待。
为了解决这个问题,可以使用一个信号量表示餐桌上最多坐四人,第5位哲学家想坐时,只能等待。
2)伪码描述:
semaphore forkLeft, forkRight, people;//左手边的叉子,右手边的叉子,允许使用桌子的人数
forkLeft.v = forkRight.v = 1;//表示两手边的叉子都处于空闲