Ark*_*avo 2 concurrency ada pragma
我需要一些帮助,也需要一些见解.这是Ada-2005中的一个程序,它有3个任务.输出为'z'.如果3个任务没有按照它们在程序中的位置顺序发生,那么输出可以从z = 2,z = 1到z = 0变化(这很容易在程序中看到,互斥是为了确保输出是z = 2).
WITH Ada.Text_IO; USE Ada.Text_IO;
WITH Ada.Integer_Text_IO; USE Ada.Integer_Text_IO;
WITH System; USE System;
procedure xyz is
x : Integer := 0;
y : Integer := 0;
z : Integer := 0;
task task1 is
pragma Priority(System.Default_Priority + 3);
end task1;
task task2 is
pragma Priority(System.Default_Priority + 2);
end task2;
task task3 is
pragma Priority(System.Default_Priority + 1);
end task3;
task body task1 is
begin
x := x + 1;
end task1;
task body task2 is
begin
y := x + y;
end task2;
task body task3 is
begin
z := x + y + z;
end task3;
begin
Put(" z = ");
Put(z);
end xyz;
Run Code Online (Sandbox Code Playgroud)
我第一次尝试这个程序
(a)没有pragma,结果:在100次尝试中,出现2:86,出现1:10,出现0:4.
然后
(b)用pragma,结果:在100次尝试中,出现2:84,出现1:14,出现0:2.
这是意料之外的,因为2结果几乎相同.这意味着编译指示或没有编译指示输出具有相同的行为.
那些Ada并发大师们请谈谈这个话题.还邀请了具有信号量的替代解决方案(如果可能的话).
在我看来,对于一个关键过程(也就是我们用Ada做的事情),对于pragma,结果应该始终为z = 2,100%,因此或者该程序应该被称为85%的关键!!!! (Ada不应该这样)
执行这三个操作的受保护对象可能看起来像这样.但请注意,所有这一切都是为了确保三个变量x,y和z与更新发生的顺序一致; 它没有说明订单.
protected P is
procedure Update_X;
procedure Update_Y;
procedure Update_Z;
function Get_Z return Integer;
private
X : Integer := 0;
Y : Integer := 0;
Z : Integer := 0;
end P;
protected body P is
procedure Update_X is
begin
X := X + 1;
end Update_X;
procedure Update_Y is
begin
Y := Y + X;
end Update_Y;
procedure Update_Z is
begin
Z := X + Y + Z;
end Update_Z;
function Get_Z return Integer is
begin
return Z;
end Get_Z;
end P;
Run Code Online (Sandbox Code Playgroud)
另一方面,为了确保三个任务以正确的顺序"提交结果",您可以重写P,以便调用说Update_Y将阻塞,直到调用Update_X:Get_Z现在必须是一个带有输出参数而不是函数.
protected P is
entry Update_X;
entry Update_Y;
entry Update_Z;
entry Get_Z (Result : out Integer);
private
X_Updated : Boolean := False;
Y_Updated : Boolean := False;
Z_Updated : Boolean := False;
X : Integer := 0;
Y : Integer := 0;
Z : Integer := 0;
end P;
protected body P is
entry Update_X when True is
begin
X := X + 1;
X_Updated := True;
end Update_X;
entry Update_Y when X_Updated is
begin
Y := Y + X;
Y_Updated := True;
end Update_Y;
entry Update_Z when Y_Updated is
begin
Z := X + Y + Z;
Z_Updated := True;
end Update_Z;
entry Get_Z (Result : out Integer) when Z_Updated is
begin
Result := Z;
end Get_Z;
end P;
Run Code Online (Sandbox Code Playgroud)
这三项任务现在可以优先考虑.但调用Update_Z的任务将阻塞,直到其他两个报告.