Lamport
Lamport算法:又称面包房算法,先来先服务算法。跟很多银行采用的排队机制一样。客户到了银行,先领取一个服务号。一旦某个窗口出现空闲,拥有最小服务号的客户就可以去空闲窗口办理业务。
Lamport算法利用前述的事件定序方案统一定序所有对临界段的请求,按先来先服务的原则让请求临界资源的进程进入其临界段,进/出临界段1次需要3×(n-1)条消息。
Lamport算法基本假定如下:
A. 进程Pi发送的请求消息形如request(Ti , i),其中Ti = Ci是进程Pi发送此消息时对应的逻辑时钟值,i代表消息内容。
B.每个进程保持一个请求队列,队列中的请求消息根据Þ关系定序,队列初始为空。
Lamport算法描述
当进程Pi请求资源时,它把请求消息request(Ti , i)排在自己的请求队列中,同时也把该消息发送给系统中的其他进程; 当进程Pj接收到外来消息request(Ti , i)后,发送回答消息reply(Tj , j),并把request(Ti , i)放入自己的请求队列。应当说明,若进程Pj在收到request(Ti , i)前已提出过对同一资源的访问请求,那么其时间戳应比(Ti , i)小。 若满足下述两条件,则允许进程Pi访问该资源(即允许进入临界段):
A. Pi自身请求访问该资源的消息已处于请求队列的最前面;
B. Pi已收到从所有其他进程发来的回答消息,这些回答消息的时间戳均晚于(Ti, i). 为了释放该资源,Pi从自己的队列中撤销请求消息,并发送一个打上时间戳的释放消息release给其他进程;
当进程Pj收到Pi的release消息后,它撤销自己队列中的原Pi的request(Ti , i)消息。
下面是我写的代码
procedure Procesus is
type MsgTypes is (REQUETE, QUITTANCE, LIBERE);
task TacheUsager;
task ExcluionMutuelle is
entry demande;
entry attente;
entry fin;
entry recoit(msgType : in MsgType; estampille, emetteur : in integer);
end ExcluionMutuelle;
task body TacheUsager is
begin
ExclusionMutuelle.demande;
ExclusionMutuelle.attente;
ExclusionMutuelle.fin;
....
....
end TacheUsager;
task body ExclusionMutuelle is
me: constant := ...;
N : constant := ...;
Time_Logique : integer:= 0;
scAccorde : boolean := false;
type t_file is record
msgType : msgTypes := LIBERE;
estampille : integer := 0;
end record;
file array (1..N) if t_file;
function Permission (me : in integer) return boolean is
accord : boolean := true;
begin
for j in 1..N loop
if j/= me then
accord := accord and (file(me).estampille < file(j).estampille) or (file(me).estampille = file(j).estampille and me < j);
end if;
end loop;
return accord;
end Permission;
begin -- ExclusionMutuelle
loop
select
accept demande;
Time_Logique := Time_Logique +1;
file(me) := (REQUETE, Time_Logique);
for j in 1..N loop
if j/= me then sent((REQUETE, Time_Logique, me),j);
end if;
end loop;
scAccorde := Permission(me);
or
when scAccorde => accept attente;
or
when seAccorde => accept fin;
file(me):= (LIBERE, Time_Logique);
for j in 1..N loop
if j/= me then sent((LIBERE, Time_Logique, me) j);
end if
end loop;
scAccord := false;
or
accept recoit(msgType : in MsgTypes; estampille, emetteur : in integer) do
Time_Logique := integer'max(Time_Logique, estampille) + 1;
case msyType is
when REQUETE => file(emetteur) := (REQUETE, estampille);
sent((QUITTANCE, Time_Logoque, me), emetteur);
when LIBERE => file(emetteur) := (LIBERE, estampille);
when QUITTANCE => if file(emetteur).msgType /= REQUETE then
file(emetteur) := (QUITTANCE, estampille);
end if
end case;
scAccorde := file(me).msgType = REQUETE and then Permission(me);
end recoit;
end select;
end loop;
end ExclusionMutuelle;
end Processus;