jan*_*anr 0 multithreading ada task
我正在学习Ada,我在理解并发模型方面遇到了一些问题.以下测试应用程序应创建3个并行运行的任务,并简单地打印一系列数字.如果我没有使用任务,entry那么一切都很好,但如果我使用条目,则程序调用块并且根本不会发生并发.
我知道有可能实现互斥和同步执行,但我无法理解如何分离任务,甚至可能创建其中的几个.
q_multithreading.ads:
package Q_MULTITHREADING is
task type TASK_LOOP is
end TASK_LOOP;
type TASK_LOOP_ACCESS is access TASK_LOOP;
--===========================================================================
task type TASK_ENTRY_LOOP is
entry P_ITERATE(to : in Integer);
end TASK_ENTRY_LOOP;
type TASK_ENTRY_LOOP_ACCESS is access TASK_ENTRY_LOOP;
--===========================================================================
procedure P_EXECUTE_NO_ENTRY;
procedure P_EXECUTE_ENTRY(to : in Integer);
end Q_MULTITHREADING;
Run Code Online (Sandbox Code Playgroud)
q_multithreading.adb:
with Ada.Text_IO;
package body Q_MULTITHREADING is
V_ID_COUNTER : Integer := 1;
--===========================================================================
task body TASK_LOOP is
V_ID : Integer := -1;
begin
V_ID := V_ID_COUNTER;
V_ID_COUNTER := V_ID_COUNTER + 1;
for i in 1 .. 15 loop
delay 0.1;
Ada.Text_IO.Put_Line("[" & Integer'Image(V_ID) & "] " &
Integer'Image(i));
end loop;
V_ID_COUNTER := V_ID_COUNTER - 1;
end TASK_LOOP;
--===========================================================================
task body TASK_ENTRY_LOOP is
V_ID : Integer := -1;
begin
V_ID := V_ID_COUNTER;
V_ID_COUNTER := V_ID_COUNTER + 1;
accept P_ITERATE(to : in Integer) do
for i in 1 .. to loop
delay 0.1;
Ada.Text_IO.Put_Line("[" & Integer'Image(V_ID) & "] " &
Integer'Image(i));
end loop;
end P_ITERATE;
V_ID_COUNTER := V_ID_COUNTER - 1;
end TASK_ENTRY_LOOP;
--===========================================================================
procedure P_EXECUTE_NO_ENTRY is
V_TASK1, V_TASK2, V_TASK3 : TASK_LOOP_ACCESS;
begin
V_ID_COUNTER := 1;
Ada.Text_IO.Put_Line("Starting task 1 ...");
V_TASK1 := new TASK_LOOP;
Ada.Text_IO.Put_Line("Starting task 2 ...");
V_TASK2 := new TASK_LOOP;
Ada.Text_IO.Put_Line("Starting task 3 ...");
V_TASK3 := new TASK_LOOP;
end P_EXECUTE_NO_ENTRY;
--===========================================================================
procedure P_EXECUTE_ENTRY(to : in Integer) is
V_TASK1, V_TASK2, V_TASK3 : TASK_ENTRY_LOOP_ACCESS;
begin
V_ID_COUNTER := 1;
V_TASK1 := new TASK_ENTRY_LOOP;
Ada.Text_IO.Put_Line("Starting task 1 ...");
V_TASK1.P_ITERATE(to); -- blocking
V_TASK2 := new TASK_ENTRY_LOOP;
Ada.Text_IO.Put_Line("Starting task 2 ...");
V_TASK2.P_ITERATE(to - 5); -- blocking
V_TASK3 := new TASK_ENTRY_LOOP;
Ada.Text_IO.Put_Line("Starting task 3 ...");
V_TASK3.P_ITERATE(to + 3); -- blocking
end P_EXECUTE_ENTRY;
end Q_MULTITHREADING;
Run Code Online (Sandbox Code Playgroud)
正如我已经提到的,如果我调用P_EXECUTE_NO_ENTRY输出是无序的,并且任务与主线程分离.另一方面*P_EXECUTE_ENTRY(to : in Integer)导致阻塞过程调用,输出就像一个不使用任务的应用程序.
如何在Ada中同时执行条目的任务?
此外,我还必须解除分配任务吗?(来自网络的例子没有这样做)
当你说
accept P_ITERATE(to : in Integer) do
for i in 1 .. to loop
delay 0.1;
Ada.Text_IO.Put_Line("[" & Integer'Image(V_ID) & "] " &
Integer'Image(i));
end loop;
end P_ITERATE;
Run Code Online (Sandbox Code Playgroud)
调用者被阻塞直到end P_ITERATE,所以整个循环完成后P_EXECUTE_ENTRY才能继续下一个任务.
要解决此问题,请将循环计数保存在任务变量中并执行以下循环accept:
accept P_ITERATE(to : in Integer) do
count := to;
end P_ITERATE;
for i in 1 .. count loop
delay 0.1;
Ada.Text_IO.Put_Line("[" & Integer'Image(V_ID) & "] " &
Integer'Image(i));
end loop;
Run Code Online (Sandbox Code Playgroud)
至于解除分配任务 - 大多数终止的程序都不会打扰,因为操作系统会在进程退出时释放内存.在这种情况下,您可能无法在任务实际终止之前解除分配; 取消分配正在运行的任务可能会导致意外行为.我认为如何管理这应该是一个不同的问题.