运用PV心法解决多线程问题

强颜欢笑 提交于 2020-03-23 11:00:32

3 月,跳不动了?>>>

    总结写在前面:

            1.注意设置的信号量的初值。

            2.不管如何变,只要牢牢的抓住同步和互斥来分析问题。

            3.先靠滤同步情况即所有“等待”情况。有几个等待”信号量类型就有几个。

            4. 接下来靠滤要互斥处理的资源。



        先讲讲PV操作的起源和用法。

        1962,荷兰学者Dijksrta在参与X8计算机的开发中设计并实现了具有多道程序运行能力的操作系统——THE Multiprogramming System。为了解决这个操作系统中进程(线程)的同步与互斥问题,他巧妙地利用火车运行控制系统中的“信号灯”(semaphore,或叫“信号量”)概念加以解决。信号量的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。注意,这个信号量的值仅能由PV操作来改变。

        PV操作由P操作原语和V操作原语组成(原语也叫原子操作Atomic Operation,是不可中断的过程),对信号量(注意不要和Windows中的信号量机制相混淆)进行操作,具体定义如下:

    P(S)

①将信号量S的值减1,即S=S-1

②如果S>=0,则该进程继续执行;否则该进程置为等待状态。

    V(S)

①将信号量S的值加1,即S=S+1

②该进程继续执行;如果该信号的等待队列中有等待进程就唤醒一等待进程。

         PV操作实现多线程的同步与互斥是非常简单的,只要靠虑逻辑处理上合理严密而不用靠虑具体技术细节,因此与写伪代码较为相似。比如有多个进程P1P2、 ……PN。它们要互斥的访问一个资源。用PV操作来实现就非常方便直观。下面是PV操作代码:

设置信号量为S初值为1。各进程的操作流程如下:

进程P1              进程P2           ……          进程Pn

PS);              PS);                           PS);

访问资源;         访问资源;                      访问资源;

VS);             VS);                          VS);

        可以看出PV操作会忽略具体的编程细节,让程序员的主要精力放在线程同步互斥的逻辑处理上。因此,通过练习PV操作能快速有效提高程序员对多线程的逻辑思维能力,达到强化“内功”的目的

        

第一题 放水果 南京大学计算机研真题

        桌上有一空盘,允许存放一只水果。爸爸可向盘中放苹果,也可向盘中放桔子,儿子专等吃盘中的桔子,女儿专等吃盘中的苹果。规定当盘空时一次只能放一只水果供吃者取用,请用PV原语实现爸爸、儿子、女儿三个并发进程的同步。

        这个题目涉及的东西非常之多,光人物就有三个再加水果,盘子等等,确实让人感觉好像无从下手。但不管题目如何变,只要牢牢的抓住同步和互斥来分析问题就必定能迎刃而解。

        下面先靠虑同步情况即所有“等待”情况:

第一.爸爸要等待盘子为空。

第二.儿子要等待盘中水果是桔子。

第三.女儿要等待盘中水果是苹果。

        接下来来靠虑要互斥处理的资源,看起来盘子好像是要作互斥处理的,但由于题目中的爸爸、儿子、女儿均只有一个,并且他们访问盘子的条件都不一样,所以他们根本不会同时去访问盘子,因此盘子也就不用作互斥处理了。分析至些,这个题目已经没有难度了,下面用PV原语给出:

先设置三个信号量,信号量Orange表示盘中有桔子,初值为0。信号量Apple表示盘中有苹果,初值为0。信号量EmptyDish表示盘子为空,初值为1。三个人的操作流程如下所示:

1.爸爸

P(EmptyDish)

if (rand()%2==0)

{   

    放桔子

    V(Orange)

}

else

{

    放苹果

    V(Apple)

}

 

2.儿子

P(Orange)

取桔子

V(EmptyDish)

 

3.女儿

P(Apple)

取苹果

V(EmptyDish)

 

 

第二题 安全岛 南开大学研真题

在南开大学至天津大学间有一条弯曲的路,每次只允许一辆自行车通过,但中间有小的安全岛M(同时允许两辆车),可供两辆车在已进入两端小车错车,设计算法并使用PV实现。

这个问题应该如何靠虑了?同样只要牢牢的抓住同步和互斥来分析问题就必定能迎刃而解。

靠虑所有“等待”情况:

在路口N准备从NT的人应该什么时候进入了?如果他只判断道路K上有没有人肯定是不行的,因为如果安全岛M上已经有2个人,那么路口N和路口T再各进一人,肯定会造成死锁。因此可以这样——在路口N准备从NT的人要等待与他同方向的人已经到达T,如果此人已经到达T,且道路K上没有人,他必定可以上路了。同理在路口T准备从TN的人也应该这样做。

再靠虑互斥情况:

路上每次只允许一辆自行车通过,所以道路是需要作互斥处理的。

 

分析之后,下面就用PV原语给出:

设置信号量NT表示在路口N且从NT方向上允许出发的自行车数量,初值为1。信号量TN表示在路口T且从TN方向上允许出发的自行车数量,初值为1。信号量KL表示道路,初值均为1。这样从NT的车和从TN的车的行驶流程如下:

NT的车                     TN的车

P(NT)                P(TN)

P(K)                 P(L)

由N到M               由T到M

V(K)                 V(L)

P(L)                 P(K)

由M到T               由M到T

V(L)                 V(K)

V(NT)                V(TN)

 

这个题目的解法有很多,比如还可以用信号量M来记录安全岛M上空位个数,初值为2。每个进入道路前的人都要先预订安全岛上的空位,订到后再互斥的进入道路。否则就要等待安全岛上有空位。信号量KL表示道路,初值均为1。然后从NT的车和从TN的车的行驶流程如下:

NT的车                 TN的车

P(M)                 P(M)

P(K)                 P(L)

由N到M               由T到M

V(K)                 V(L)

P(L)                 P(K)

V(M)                 V(M)

由M到T               由M到T

V(L)                 V(K)

 

        这种解决方法也是不会造成死锁的。安全岛的解法非常之多,网上还有不少不同的解法,有兴趣的童鞋可以搜索一下。




易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!