进程同步算法

进程的组成

进程由以下内容组成:
PCB:进程控制块,是进程的唯一标识
程序,数据区,工作区

进程的三态

运行态,就绪态,阻塞态

进程之间的互斥

多个进程因争用临界资源而互斥执行,叫做进程间的互斥。实现进程互斥的方法有以下几种:

  • Dekker算法:这种算法需要设置一个整型变量turn,用来指示允许进入临界区的线程,turn=1表示P1可以进入临界区,turn=2表示P2可以进入临界区。还要设置一个flag[2]数组表示自己是否愿意进入临界区。flag[0]=true表示进程P1愿意进入临界区,为false表示不愿意进入临界区,flag[1]与P2对应。Dekker算法采用竞争的方式来进入临界区,假如P1想进入临界区,它将自己的flag[0]=true,然后看P2是否愿意进入临界区,如果P2不愿意,那么P1直接进入临界区。如果P2也愿意进入临界区,那么查看turn的值,看当前轮到谁进入临界区了。如果轮到P2进入临界区了,那么P1则表示自己不愿意进入临界区(flag[0]=flase)。将进入临界区权限让给P2.然后一直等P2从临界区退出。

示例代码

void P0()
{
	while(true)
	{
		flag[0] = true;//P0想使用关键区。
		while(flag[1])//检查P1是不是也想用?
		{
			if(turn == 1)//如果P1想用,则查看P1是否具有访问权限?
			{
				flag[0] = false;//如果有,则P0放弃。
				while(turn == 1);//检查turn是否属于P1。
				flag[0] = true;//P0想使用。
			}
		}
		visit(0); //访问Critical Partition。
		turn = 1; //访问完成,将权限给P1。
		flag[0] = false;//P0结束使用。
	}
}
void P1()
{
	while(true)
	{
		flag[1] = true; //P1想使用关键区。
		while(flag[0]) //检查P0是不是也想用?
		{
			if(turn == 0) //如果P0想用,则查看P0是否具有访问权限?
			{
				flag[1] = false; //如果有,则P1放弃。
				while(turn == 0); //检查turn是否属于P1。
				flag[1] = true; // P1想使用。
			}
		}
		  visit(1); //访问Critical Partition。
		turn = 0; //访问完成,将权限给P0。
		flag[1] = false; //P1结束使用。
	}
}
  • Peterson算法:这种算法与Dekker算法很相似,但是采用谦让的态度。turn和flag[2]都少不了,而且其含义与Dekker算法一样。先表示自己愿意进入临界区,然后将进入临界区的权限让给对方。

示例代码

void procedure0()
{
	while(true)
	{
		flag[0] = true;
		turn = 1;  //将进入临界区权限让给对方
		while(flag[1] && turn == 1)
		{
			sleep(1);
			printf("procedure0 is waiting!
");
		}
		//进入临界区
		flag[0] = false;
	}
}
void procedure1()
{
	while(true)
	{
		flag[1] = true;
		turn = 0;
		while(flag[0] && turn == 0)
		{
			sleep(1);
			printf("procedure1 is waiting!
");
		}
		//进入临界区
		flag[1] = false;
	}
}

这两种算法都会出现忙等待现象,造成资源的浪费。

硬件方法:“开关中断”指令,“交换”指令,“测试与设置”指令,这三种需要CPU指令集的支持,来达到互斥的目的。

进程的同步

进程之间的同步一般使用信号量来实现,P操作获取资源,V操作释放资源。下面是生产者--消费者模型。P1和P2共享缓冲区,S1和S2的初值为1和0。缓冲区满则不能放物品,缓冲区空不能拿物品。缓冲区只能放一件物品。

P1进程

while(true) {
	生产一件产品;
	P(S1); /*申请空缓冲区*/
	放入物品;
	V(S2);
}

P2进程

while(true) {
	P(S2); /*申请满缓冲区*/
	获取物品;
	V(S1);
}

P操作会消耗资源,V操作会释放资源。S>0时表示同类资源可用数量,S=0表示无可用资源,S<0时,S的绝对值表示正在被阻塞的进程数量。

进程与线程

进程是资源分配的单位,线程是调用的基本单位。线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(寄存器,栈,程序计数器),它与同一个进程的其他线程共享进程所拥有的全部资源。线程的切换相比于进程来说开销更小(切换时换入换出的内容比进程要小的多,所以速度快)。

死锁产生的必要条件

  • 互斥资源的使用(资源独占):自己占有了资源,其它进程就无法共享使用
  • 不可剥夺:自己占有的资源不能被剥夺,直到主动释放为之
  • 零散请求:不能一次性将所有资源拿到手
  • 循环等待:等待资源的进程形成一个环

只要破坏上面的一个条件就不会发生死锁。这是从预防的角度出发,即对资源的申请加以严格的限制,从而不会发生死锁。

死锁的避免

死锁的避免是在进程申请资源之前,看预判一下,满足进程的要求后会不会发生死锁。如果会发生则不分配,如果不发生则分配资源。

单银行家算法

在某一时刻,系统的某种资源(这里是资金)剩余4,这时有四个进程都要申请这种资源,则应将资源分给a或b让其执行。a或b执行后会释放自己占有的资源,这样其它进程可以继续执行了。

多银行家算法

单银行家算法是对单个资源的分发控制,而多银行家算法则控制多个资源。

图a中表示每个进程总共要申请的资源数,图b表示每个进程已经申请到的资源,图c表示每个进程还需要申请的资源。然后给出分配策略。

原文地址:https://www.cnblogs.com/xidongyu/p/6559625.html