目录
一. 进程同步与进程互斥
进程有异步性的特征,所谓异步性就是并发执行的进程以各自独立的、不可预知的速度向前推进,这个时候就不可避免的出现有些请求由于资源不足等原因而不能完成,所以为了使进程可以顺利的进行,操作系统引入了进程同步机制。
1.1 进程同步
举一个例子,在前面提到的管道通信中,读进程发生的前提一定是写进程在管道内已经写了数据,但是由于并发的异步性,读进程、写进程这两个进程的执行顺序是不可预知的,所以很有可能出现先读后写这样的问题。为了解决这种异步性带来的问题就引入了进程同步。
同步亦称直接制约关系,它是指为完成某种任务而建立的两个或多个进程,这些进程因为需要在某些位置上协调它们的工作次序而产生的制约关系。进程间的直接制约关系就是源于它们之间的相互合作。
1.2 进程互斥
"互斥",顾名思义就是互相排斥的意思。进程互斥指当一个进程访问某临界资源时,另一个想要访问该临界资源的进程必须等待当前访问临界资源的进程访问结束,释放该资源之后,另一个进程才能去访问临界资源。
对临界资源的访问从逻辑上可以分为以下四个部分:
repeat
entry section; //进入区
critical section; //临界区
exit section; //退出区
remainder section; //剩余区
until false;
其中,进入区是负责检查是否可以访问临界资源,若可以进入就应该设置“锁”,暂时将此资源上锁,防止其他进程访问;临界区是访问临界资源的那段代码;退出区与进入区正好相反他可以在进程访问完资源后对资源进行解锁;剩余区会完成剩余的一些操作。在以上四个部分中,进程互斥主要是靠上锁以及解锁实现的。
思考一个问题,如果某个资源在进入区被挡住了。那他会一直占着处理机来申请进入临界区吗?肯定不会的,这是因为进程互斥遵循以下四个原则:空闲让进、忙则等待、有限等待、让权等待
空闲让进:临界区空闲时,可以允许一个请求进入临界区的进程立即进入临界区。
忙则等待:当已有进程进入临界区时,其他试图进入临界区的进程必须等待。
有限等待:对请求访问的进程,应保证能在有限时间内进入临界区(保证不会饥饿)。
让权等待:当进程不能进入临界区时,应立即释放处理机,防止进程忙等。
二. 进程互斥的软件实现方法
2.1 单标志法
两个进程在访问完临界区后会把使用临界区的权限转交给另一个进程。也就是说每个进程进入临界区的权限只能被另一个进程赋予。
int turn = 0; //turn表示当前运行的进程编号
P0进程 P1进程
while(turn != 0); 1 while(turn != 1); 5 //进入区
critical section; 2 critical section; 6 //临界区
turn = 1; 3 turn = 0; 7 //退出区
remainder section; 4 remainder section; 8 //剩余区
在这里turn就是一个标志,表示的是"让步"。turn 的初值为 0,即刚开始只允许 0 号进程进入临界区。若 P1 先上处理机运行,则会一直卡在 5。直到 P1 的时间片用完,发生调度,切换 P0 上处理机运行。代码1(注意这个while后面是个分号表示此语句已完成而不是一个循环语句) 不会卡住 P0,P0 可以正常访问临界区,在 P0 访问临界区期间即时切换回 P1,P1依然会卡在 5。只有 P0 在退出区将 turn 改为 1 后,P1才能进入临界区。
我们仔细手动推演一下代码不难发现,此时进程调度是按P0 P1 P0 P1...轮流交替调度的,虽然可以实现互斥,但是如果在P0允许进入临界区时,P0却不想访问临界资源,那么处理机就会空闲此时P1去不能够进行访问,所以,这种方法不满足”空闲让进“原则。
2.2 双标志先检查法
设置一个布尔型数组 flag[],数组中各个元素用来标记各进程想进入临界区的意愿,比如“flag[0] = ture”意味着 0 号进程 P0 现在想要进入临界区