在考虑写代码以前应该先考虑咱们要用什么数据结构?以及该数据有什么意义。算法
P0: { while(turn != 0) ; // critical section turn = 1; // 退出区 // remainder section } P1: { while(turn != 1) ; // critical section turn = 0; // 退出区 // remainder section }
在这里,为了实现互斥使用了一个共享变量turn。
为何有效?数据结构
在任意时刻turn的取值只能为0或1.所以条件
while(turn != X)
有且仅有一个会被知足,于是使得一个进程得以访问临界区。(至于turn被谁修改,何时修改,都不会对该过程产生不利影响)
有什么不足?并发
一个标识符只有2个信息。它只能表示1.P0干完了.2.P1干完了。 因此当P0干完了,P1又不干活的时候,P0还傻傻的等P1
turn表示什么?code
turn实际上是进程间约定的执行顺序。2个进程约好轮班工做,一个在干完活了通知另外一个,反复交替。turn能够理解为许可证,只有持有turn的进程才能进去工做。就好像看病取票排队同样。
P0: { while(busy) ; busy=1; // critical section busy = 0; // 退出区 // remainder section } P1: { while(busy) ; busy=1; // critical section busy = 0; // 退出区 // remainder section }
这是一个典型的错误方法。
为何出错?busy表示什么?进程
busy像是一扇大门,先进去的人从里面反锁不让外面的人进来。里面的人出来之后再从新开门。可是busy也只有2个信息量,也就是开和关。当它开门的时候没法控制进入的数量。因此极有可能一会儿进去好多人。
可是它解决了前面的一个问题:没法“空闲让进”。rem
P0: { flag[0]=1;turn=0; while(flag[1]&&turn != 0) ; // critical section flag[0]=0;// 退出区 // remainder section } P1: { flag[1]=1;turn=1; while(flag[0]&&turn != 1) ; // critical section flag[1]=0;// 退出区 // remainder section }
flag是什么?it
首先看循环等待条件flag[1]&&turn != 1
,对其取反即为经过条件!flag[1]||turn==1
。所以进入临界区的条件是得到许可(turn==1)或者P1空闲(!flag[0])。flag为0表示进程很空,flag为1表示想要进入临界区(不必定进入)。这里能够形象地理解为2个进程都盯着对方,一旦对方空了下来,就立刻冲过去。
这里的turn有点不同!io
这里再也不是轮班工做了。而是在表达完进入的意愿后(flag置1)将turn设为本身。说白了就是争夺模式。最后只有一个进程抢到turn,另外一就等待对方空闲退出。
这个算法其实也不太完美,经过以上分析很容易就能知道它只容许2个进程的并发。多进程
警告:该算法自创,未来程序出了差错,我是不会负责的class
结合一下前面几种方法,尽量地减小信息量,还要解决多进程的并发问题。如今再整理一下思路。首先,须要一个大门。而后门后面须要取票排队。
Pi: { while(true) { while(flag) ;//等待空闲 flag=1;//占用 turn=i; if(turn==i) break; } // critical section flag=0;// 退出区 // remainder section }
如何工做?
利用flag控制大门开关。当里面没人时,立刻进入,进去后就赶忙把门反锁(flag=1)。此时是有可能多个进程同时溜进去的,怎么办呢?划拳把!(turn=i)总之无论怎么样,最后turn为这帮人中的某一个,所以有且仅有一个得以进入,其余的则被轰出门外从新寻找机会。