现在的位置: 首页 > 综合 > 正文

Dining philosophers problem

2013年08月27日 ⁄ 综合 ⁄ 共 2982字 ⁄ 字号 评论关闭

 

 经常使用的方法:

  Locking a resource is a common technique to ensure the resource is accessed by only one program or chunk of code 

 

at a time.

 

算法

 

Waiter solution

 

引入一个服务员 Philosophers must ask his permission before taking up any forks. Because the waiter is aware of 

 

which forks are in use, he is able to arbitrate and prevent deadlock. 

 

//这个方法的关键是引入了一个全局监视变量,可以轻松完成监控分配。

 

 

 

Resource hierarchy solution

 

Another simple solution is achieved by assigning a partial order, or hierarchy, to the resources (the forks, in 

 

this case), and establishing the convention that all resources will be requested in order, and released in reverse 

 

order, and that no two resources unrelated by order will ever be used by a single unit of work at the same time.

 

This is often the most practical solution for real world Computer Science problems; by assigning a constant 

 

hierarchy of locks, and by enforcing the ordering of obtaining the locks this problem can be avoided.

 

//这个解法的关键在于引入了偏序关系,之后的很多事情变得很简单了。

 

Chandy / Misra solution

 

 

1  For every pair of philosophers contending for a resource, create a fork and give it to the philosopher with the 

 

lower ID. Each fork can either be dirty or clean. Initially, all forks are dirty. 

2  When a philosopher wants to use a set of resources (i.e. eat), he must obtain the forks from his contending 

 

neighbors. For all such forks he does not have, he sends a request message. 

3  When a philosopher with a fork receives a request message, he keeps the fork if it is clean, but gives it up 

 

when it is dirty. If he sends the fork over, he cleans the fork before doing so. 

4  After a philosopher is done eating, all his forks become dirty. If another philosopher had previously requested 

 

one of the forks, he cleans the fork and sends it. 

 

//不断在状态更迭中转换标记状态。很奇妙的一个东西。。

 

code:

 

PROGRAM d_p;

CONST

   DoomsDay = FALSE;

MONITOR dining_philosophers;  // initialize use of monitors

CONST

   Eating   = 0;   

   Hungry   = 1;

   Thinking = 2;

VAR

   i     : INTEGER; // init loop variable

   state : ARRAY [0..4] OF INTEGER; // Eating, Hungry, Thinking

   self  : ARRAY [0..4] OF CONDITION; // one for each Philospher 

   // place for Hungry Ph to wait until chopsticks become available 

PROCEDURE test(k : INTEGER);

  // if k's left & right neighbors aren't Eating & k is Hungry 

  // then change k's state to Eating & signalc (in case k is waitc-ing)

BEGIN

   IF (state[(k+4) MOD 5] <> Eating) AND (state[k] = Hungry) AND

      (state[(k+1) MOD 5] <> Eating) THEN {right neighbor}

   BEGIN

      state[k] := eating;

      SIGNALC(self[k]); //tell k to eat if k is waitc-ing

   END; 

END; 

PROCEDURE pickup(i: INTEGER);

BEGIN

   state[i] := Hungry;

   WRITELN('philosopher ',i,' hungry');

   test(i); // are my neighbors eating? 

   IF state[i] <> Eating THEN // waitc if they are (sleep mode)

      WAITC(self[i]);  

   WRITELN('philosopher ',i,' eating');

END; 

PROCEDURE putdown(i : INTEGER);

BEGIN

   state[i] := Thinking;

   WRITELN('philosopher ',i,' thinking');

   test( (i+4) MOD 5); // give left neighbor chance to eat 

   test( (i+1) MOD 5); // give right neighbor chance to eat 

END;  

BEGIN // monitor initialization

   FOR i := 0 TO 4 DO state[i] := Thinking;

END;  // dining_philosopher monitor

 

PROCEDURE philosopher(i : INTEGER);

BEGIN

   REPEAT

      pickup(i);  // pick up chopsticks 

      putdown(i); // put down chopsticks 

 

   UNTIL DoomsDay;

END; 

 

BEGIN  

   COBEGIN  // process to being all five processes at once

      philosopher(0); philosopher(1); philosopher(2);

      philosopher(3); philosopher(4);

   COEND;

END

 

 

 

 

抱歉!评论已关闭.