同步与互斥(实现临界区互斥的方法、同步与互斥的基本概念)

实现临界区互斥的方法、同步与互斥的基本概念

有关同步和互斥基本概念

为什么要引入进程同步的概念?

在多道程序环境下,进程是并发执行的,不同进程之间存在着不同的相互制约关系。为了协调相互制约关系,引入了进程同步的概念

临界资源

一次仅仅允许一个进程使用的资源被称之为临界资源

临界资源的种类:输入机(键盘)、打印机、磁带机等

临界区

进程中访问临界资源的那段代码,又称之为临界段

补充:当有线程进入临界区段时其他线程或者进程必须进入等待状态之中。

原子操作

原子操作指的是不会被线程调度机制打断的操作,且这种操作一旦执行,就会一直运行直到结束,中间不会有任何线程切换。

保证线程持续运行的一种机制。

只有第一个申请到锁的进程才能够继续运行。

本质:由一位内存、一个阻塞队列和申请锁、释放锁的方法组成的数据结构

进程同步

并发的多个进程(线程)按照某种次序执行某种程序以合作完成某种功能的制约关系。

补充:同步也被称之为直接制约关系。

互斥

当一个进程进入临界区使用临界资源时,另外一个进程必须等待,当其退出时才能进入下一个进程。

死锁

死锁:多个进程全部阻塞,形成等待资源的循环链

饥饿

饥饿:一个就绪进程被调度程序长期忽视、不被调度执行;一个进程长期得不到资源

临界区的访问规则

为了禁止两个进程同时进入临界区,同步机制应该遵循以下基本规则

  1. 空闲让进:没有任何进程在临界区的时,允许进入
  2. 忙则等待 : 临界区存在进程的时候,其他进程不允许进入临界区
  3. 有限等待: 等待进入临界区的进程不能一直(无限)等待
  4. 让权等待: 不能进入临界区的进程,应立即释放cpu(如转换到阻塞状态)

临界区 互斥的基本方法——软件实现方法

单标志法

//P0进程
while(turn!=0);		  //进入区
	critical section; //临界区
	turn=1;			//退出区
	remainder section; //剩余区
//P1进程
while(turn!=1);       //进入区
	critical section;	//临界区
	turn=0;				//退出区
	remainder section;		//剩余区

该方式设置⼀个公用的整型变量 turn ,用于指示被允许进入临界区的进程编号,若 turn=0 ,则允许 P0 进程进入临界区;若 turn=1 ,则允许 P1 进程进入临界区。 为什么要设置两个不同的turn量,即trun=0 or turn=1;

因为从上述代码可得,该方式只能⽀持两个进程交替轮流进⼊临界区。

考虑这样⼀个情形: 进程使⽤完临界资源,退出临界区后,此时 turn=1 ,但进程没有进⼊临界区的打算,那么 turn 变量永远不会变 为 0(因为只有进程使⽤临界资源后才会置 turn=0 ),这样 就无法再次进⼊临界区,然而此时临界区是空闲的,该方式违背了“空闲让进”的准则。

双标志先检查法

//Pi进程
while(flag[j]); //STEP1
	flag[i]=TRUE; //STEP3
	critical section;
	flag[i]=FALSE;
	remainder section
//Pj进程
while(flag[i]); //STEP2
	flag[j]=TRUE; //STEP4
	critical section;
	flag[j]=FALSE;
	remainder section;

单标志法的缺陷:

由于单标志法只能支持两个进程交替进⼊临界区,归根结底的原因就是只使用了 turn ⼀个变量,只能表示 P0 在临界区内或 P1 在临界区内两种状态,这种方式就隐含了这样⼀层意思:==P0 不在临界区内那 P1 ⼀定在临界区内; P1 不在临界区内那 P0 ⼀定在临界区内,==这就是单标志带来的局限性:可表示的状态过少。

那么双标志法就引⼊了多个标志位: flag 数组,其中 flag[i]=TRUE 就代表进 程 在临界区内,反之 flag[i]=FALSE 就代表进程 不在临界区内。

优点:不要求进程交替进入,单个进程可以连续使用临界区。

缺点: 按照 STEP1~4 的顺序执行时, Pi 和 Pj 进程可能会同时进入临界区,这样就违背了“忙则等待”

补充 : 造成缺点的原因

检测操作(while 语句)和修改操作(赋值语句)不是⼀次性完成的,即缺失了原⼦性。

双标志后检查法

//Pi进程
flag[i]=TRUE;
while(flag[j]);
	critical section;
	flag[i]=FALSE;
	remainder section;

//Pj进程
flag[j]=TRUE;
while(flag[i]);
	critical section;
	flag[j]=FALSE;
	remainder section;

种方式改变了双标志先检查法中检测操作和赋值操作的顺序,避免了两个进程同时进入临界区,然而会造成两个进程都不能进入临界区,违背了“空闲让进”的准则,造成“饥饿现象”。

Peterson算法

//Pi进程
flag[i]=TRUE;turn=j;
while(flag[j]&&turn==j);
	critical section;
	flag[i]=FALSE;
	remainder section;
//Pj进程
flag[j]=TRUE;turn=i;
while(flag[i]&&turn==i);
	critical section;
	flag[j]=FALSE;
	remainder section;

turn 在某⼀时刻的值肯定是确定的,让两个进程相互谦让,都将 turn 置为对方进程的编号,最后 turn 的值只能是其中⼀个,就代表其中⼀个进程的谦让是无效的,因此能够成功解决两个进程都不能进入临界区的尴尬局面。

优点:遵循了 空闲让进 忙则等待 有限等待三个准则,不符合让权等待

补充:此算法利用flag 数组解决临界资源的互斥访问,利用turn 变量解决“饥饿”现象。

临界区 互斥的基本方法——硬件实现方法

中断屏蔽法

方法: 进入临界区:禁用所有中断。

离开临界区:使能所有中断。

缺点:

  1. 禁用中断后,进程无法被停止。整个系统都会为此停下来,其它进程可能进入饥饿状态。
  2. 临界区可能很长,此间全部禁用中断可能会出现意料之外的问题。
  3. 不适合多处理机,只适合操作系统内核进程,不适合于用户进程

硬件指令方法——TestAndSet指令

boolean TestAndSet(boolean *lock){
	boolean old;
	old=*lock;
	*lock=TRUE;
	return old;
}

为每个临界资源设置⼀个布尔变量 lock ,表⽰该资源的两种状态:TRUE ⽰正在被占⽤;FALSE 表⽰当前没有被占⽤,初值为 FALSE。利⽤ TestAndSet 指令实现互斥的过程描述如下:

while(TestAndSet(&lock));
	临界区代码段;
	lock=FALSE;
	其他代码;

优点:适用于多处理器系统 ,变成了原子操作

缺点: 暂时无法进入临界区的进程会占用cpu循环执行ts指令,因此不能实现“让权等待”

硬件指令方法——Swap指令

void Swap(boolean *a, boolean *b){
	boolean tmp;
	tmp=*a;
	*a=*b;
	*b=tmp;
}

利用Swap指令实现互斥的过程描述如下,其中 key 时进程的局部布尔变量, lock 是每⼀个临界资源的共享布尔变量:

key=TRUE;
while(key!=FALSE){
	Swap(&lock, &key);
}
临界区代码段;
lock=FALSE;
其他代码;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值