进程间的交互分为竞争关系、协作关系。
1、竞争关系
由于计算机内资源有限,或者说某几个进程必须共享某些资源与变量,这时候就不可避免的会出现竞争,进程的相互竞争就会穿死锁和饥饿问题,饥饿问题已解释。
死锁问题是指一组进程如果都获得了部分资源,还想要得到其他进程占用的资源,最终所有进程都将陷入死锁,即都在等待,每个进程都不会先放手自己占有的资源。
进程互斥:若干进程在使用共享资源的时候,其他进程必须等待正在使用的进程释放该进程,临界区管理是解决进程互斥问题的办法。
2、协作关系
某些任务需要很多进程为其分工来完成,这时候需要协调互相之间的关系,比如某个进程在进行到某个点之后需要等待某些进程的消息和信号才能继续执行。(进程同步。
临界区:并发进程中与共享变量有关的程序段叫“临界区”。
临界资源:共享变量代表的资源叫做“临界资源”。
临界区调度原则:空闲让进、忙则等待、有限等待、让权等待。
3、信号量解决
p表示获取资源,一般会跟value--,v表示释放资源,后接value++。p、v一定是成对出现在同一个进程之中,否则会出现资源泄漏。
经典问题:哲学家进餐问题、生产者消费者问题、读写者问题、理发师问题。
哲学家进餐问题:五个哲学家围坐一张圆桌,桌上仅有五根筷子,每位哲学家只能拿起与他相邻的两根筷子吃饭。五根筷子都是临界资源
设为:semaphore fork[5] = {1,1,1,1,1};
philosopher_i()
while(true){
{think()};
p(fork[i]);
p(fork[(i+1)%5]);
{eat()};
v(fork[i]);
v(fork[(i+1)%5]);
}
此法会造成死锁问题,比如五个哲学家进程同时启动,则在申请第二个筷子的时候,所有进程都会等待别的进程释放手中的资源,这就是死锁。破解:1可以设置条件,只有当左右两边的筷子都空闲的时候,才允许去拿筷子(AND信号量机制);2只允许最多四个人同时去拿筷子,这样总有一个人能拿到两个完成进程,最后释放资源;
生产者消费者问题:顾名思义,生产的同时有消费。
设置缓冲区buf[n],以便协调生产与消费的速度,但对缓冲区的访问必须是互斥的,否则还没生产即被消费。
设置互斥信号量为mutex初始化为1,empty表示buf内空余区数,初始化为n,full相反,初始化为0,。
process producer()
while(true)
{
produce an item in nextp;
p(empty);//empy--
p(mutex);mutex = 1
buf[in] = nextp;
in = (in+1)%k;//round buffer
counter++;
v(mutex);//mutex = 0
v(full);//full++
}
process consumer()
while(true)
{
p(full);
p(mutex);
nextc = buf[out];
out = (out+1)%k;
counter--;
v(mutex);
v(empty);
consume item nextp
}
读写者问题:多个进程共享一个数据区,读进程只读,写进程只写。如售票系统的查询与更新,如果没有比较好的控制会出现同时售出同一张票这种情况。
可以设置mutex为读者之间的互斥访问,wrt为写者之间以及写者与读者之间的互斥访问。
当没有写者进程,多读者进程可以并发,当有读者进程的时候,写者进程阻塞。称为读者优先。
process reader()
while(true){
p(mutex);
readercount++;
if(readercount>=1) p(wrt);
v(mutex);
reading data;
p(mutex);
readercount--;
if(readercount==0) v(wrt);
v(mutex);
}
process writer()
while(true){
p(wrt);
writing data;
v(wrt);
}
写者优先:上述读者优先实际上也不是优先读者,只是相对写者优先来说的概念。
写者优先需要设置wrt控制写者之间的冲突、readcount计数读者,writecount计数写者,读者之间的互斥rmutex,读写者之间的互斥rwmutex(控制由写者优先);
process reader()
while(true){
p(rwmutex);
p(rmutex);
readcount++;
if(readcount == 1) p(wdr);//有读进程,控制不可以写
v(rmutex);
v(rwmutex);
read data..........
p(rmutex);
readcount--;
if(readcount==0) v(wdr);
v(rmutex);
}
process writer()
while(true){
p(wmutex);
writercount++;
if(writercount==1) p(rwmutex);
v(wmutex);
p(wrt);
{writing......}
v(wrt);
p(wmutex);
writercount--;
if(writercount==0) v(rwmutex);
v(wmutex);
}