任务不是运行并发

Tasks are not run concurrently

怎样才能同时得到这些任务运行,这样"Hello World from N"的消息就会混在一起?

除了 1、2 或 3 可以互换之外,我的输出看起来总是这样。

Hello World from 1!
Hello World from 2!
Hello World from 3!

看起来不像任务 运行 并发。它看起来像 运行 连锁店,先到先得。

main.adb

with Ada.Text_IO;

procedure Main is
   type Runnable_Type is access procedure;

   task type Filter (Runnable_Access : Runnable_Type) is
      entry start;
   end Filter;

   task body Filter is
   begin
      accept start;
      Runnable_Access.all;
   end Filter;

   procedure Run_1 is
   begin
      Ada.Text_IO.Put_Line ("Hello World from 1!");
   end Run_1;

   procedure Run_2 is
   begin
      Ada.Text_IO.Put_Line ("Hello World from 2!");
   end Run_2;

   procedure Run_3 is
   begin
      Ada.Text_IO.Put_Line ("Hello World from 3!");
   end Run_3;

   Filter_1 : Filter (Run_1'Access);
   Filter_2 : Filter (Run_2'Access);
   Filter_3 : Filter (Run_3'Access);
begin
   Filter_1.start;
   Filter_2.start;
   Filter_3.start;
end Main;

任务运行并发。他们只是没有做足够的事情来让这种并发可见。为每项任务添加更多工作,例如反复打印一行文字,你就会看到了。

使用Text_IO.Put_Line很可能导致整行在一个操作中写入,尽管它可能是两个操作(一个输出字符串中的字符,一个输出换行符)是合理的).但是 OS 输出字符串的调用(可能没有换行符)可能是一次调用,并且 OS 操作可能是不可中断的,或者它可能运行得太快以至于很难中断带线程开关。无论如何,这可能不会一次输出一个字符。 (我假设您 运行 宁在 Linux 或 Windows 系统或类似系统上,而不是具有最小 运行 时间等的嵌入式系统。 )

您可以自己一次输出一个字符:

procedure Output_String (S : String) is
begin
    for I in S'range loop
        Text_IO.Put (S (I));
        --delay 0.0;
    end loop;
    Text_IO.New_Line;
end Output_String;

然后让您的 Run 程序调用它而不是 Text_IO.Put_Line。如果在没有 delay 0.0 的情况下它不起作用,请尝试使用此延迟,因为它可能会导致程序寻找与 运行 具有相同优先级的其他就绪任务。不过,我不能保证任何事情。

正如 Jack 所说,它们是 运行 同时进行的。在 Run_* 过程的不同部分放置一个忙循环表明了这一点。

with Ada.Text_IO;

procedure Main is
   type Runnable_Type is access procedure;

   task type Filter (Runnable_Access : Runnable_Type) is
      entry start;
   end Filter;

   task body Filter is
   begin
      accept start;
      Runnable_Access.all;
   end Filter;

   procedure Run_1 is
      counter : integer := 0;
   begin
      for i in 1..1000000 loop
         counter := counter + 1;
      end loop;
      Ada.Text_IO.Put_Line ("Hello World from 1a!");
      Ada.Text_IO.Put_Line ("Hello World from 1b!");
      Ada.Text_IO.Put_Line ("Hello World from 1c!");
   end Run_1;

   procedure Run_2 is
      counter : integer := 0;
   begin
      Ada.Text_IO.Put_Line ("Hello World from 2a!");
      for i in 1..1000000 loop
         counter := counter + 1;
      end loop;
      Ada.Text_IO.Put_Line ("Hello World from 2b!");
      Ada.Text_IO.Put_Line ("Hello World from 2c!");
   end Run_2;

   procedure Run_3 is
      counter : integer := 0;
   begin
      Ada.Text_IO.Put_Line ("Hello World from 3a!");
      Ada.Text_IO.Put_Line ("Hello World from 3b!");
      for i in 1..1000000 loop
         counter := counter + 1;
      end loop;
      Ada.Text_IO.Put_Line ("Hello World from 3c!");
   end Run_3;

   Filter_1 : Filter (Run_1'Access);
   Filter_2 : Filter (Run_2'Access);
   Filter_3 : Filter (Run_3'Access);
begin
   Filter_1.start;
   Filter_2.start;
   Filter_3.start;
end Main;

输出为:

Hello World from 2a!
Hello World from 3a!
Hello World from 3b!
Hello World from 2b!
Hello World from 2c!
Hello World from 1a!
Hello World from 1b!
Hello World from 1c!
Hello World from 3c!