问题描述
受保护对象机制不仅可以用于共享数据,还可以用于同步 动作。这是一种(尝试)同步所有任务并释放所有任务的模式 一旦所有任务准备就绪即可进行。条目上的Count属性可方便地用于此目的,因为它指示当前在此特定条目上等待的任务数。在这里我们打开 条目根据等待的任务数量进行同步:
with Ada.Task_Identification; use Ada.Task_Identification;
with Ada.Text_IO; use Ada.Text_IO;
procedure Synchronized_Action is
No_Of_Tasks : constant Positive := 5;
protected type Blockers (Group_Size : Positive) is
entry Synchronize;
end Blockers;
protected body Blockers is
entry Synchronize when Synchronize’Count = Group_Size is
begin
null;
end Synchronize;
end Blockers;
Blocker : Blockers (No_Of_Tasks);
task type In_Synchronized_Stages;
task body In_Synchronized_Stages is
begin
Put_Line (“Task “ & Image (Current_Task) & “ starting up”);
delay 1.0;
Blocker.Synchronize;
Put_Line (“Task “ & Image (Current_Task) & “ in stage 1”);
delay 1.0;
Blocker.Synchronize;
Put_Line (“Task “ & Image (Current_Task) & “ in stage 2”);
end In_Synchronized_Stages;
Staged_Tasks : array (1 .. No_Of_Tasks) of In_Synchronized_Stages;
begin
null;
end Synchronized_Action;
现在我不得不承认这个程序看起来比运行的更好:它“挂起”-或至少看起来像 除了最耐心的用户外,所有其他用户都无法使用。该程序的思想是,所有任务在各个阶段之间重新同步,这样,任何任务都不应在以后的阶段中完成所有工作,而其他任务 早期阶段任务仍然很忙。 修复此程序,使其确实显示预期的行为并运行完毕。 提示:您期望在屏幕上看到输出的时间顺序是什么?什么 实际输出的节奏是什么?这怎么可能发生? … 现在轮到你 显示看到错误(对吗?)并可以修复它。
以下实现确实可以完成,但是大约需要0.5秒。可以做些什么来使其更快?
with Ada.Task_Identification; use Ada.Task_Identification;
with Ada.Text_IO; use Ada.Text_IO;
procedure Synchronized_Action is
No_Of_Tasks : constant Positive := 5;
protected type Blockers (Group_Size : Positive) is
entry Synchronize;
private
Triggered : Boolean := False;
end Blockers;
protected body Blockers is
entry Synchronize when Synchronize'Count = Group_Size or Triggered is
begin
if Synchronize'Count = 0 then
Triggered := False;
else
Triggered := True;
end if;
end Synchronize;
end Blockers;
Blocker : Blockers (No_Of_Tasks);
task type In_Synchronized_Stages;
task body In_Synchronized_Stages is
begin
Put_Line ("Task " & Image (Current_Task) & " starting up");
delay 0.0;
Blocker.Synchronize;
Put_Line ("Task " & Image (Current_Task) & " in stage 1");
delay 0.0;
Blocker.Synchronize;
Put_Line ("Task " & Image (Current_Task) & " in stage 2");
end In_Synchronized_Stages;
Staged_Tasks : array (1 .. No_Of_Tasks) of In_Synchronized_Stages; pragma Unreferenced (Staged_Tasks);
begin
null;
end Synchronized_Action;
解决方法
与您在other question中遇到的困难相比,这是相当复杂的代码,所以我想知道它们是否是课堂问题,即家庭作业?
第一个版本失败的原因是每次激活后都会重新评估输入条件,因此当第一个任务完成时,输入队列中只有4个任务。
无论如何,如果排队策略(ARM D.4)不是FIFO_Queuing,那么我不禁觉得第二版可能存在相关问题。