2016-05-24 12 views
0

私はAdaを学習していますが、並行性モデルの理解にはいくつか問題があります。次のテストアプリケーションは、並行して動作する3つのタスクを作成し、単純に一連の数値を出力します。 entryのないタスクを使用するとすべて問題ありませんが、エントリを使用するとプロシージャコールブロックが発生し、並行性はまったく発生しません。Adaでのマルチスレッド化

相互排除と同期実行を実現する可能性があることを理解していますが、タスクの分離方法を理解できず、複数のタスクを作成することも可能です。

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; 

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; 

私はすでに述べたように、私はP_EXECUTE_NO_ENTRYを呼び出す場合、出力が乱れているとタスクはメインスレッドから切り離されています。一方、*P_EXECUTE_ENTRY(to : in Integer)は、ブロッキングプロシージャコールにつながり、出力はタスクを使用しないアプリケーションのようです。

Adaで同時にエントリが実行されているタスクはどのようになっていますか?

さらに、タスクの割り当てを解除する必要がありますか?

+1

あなたは 'new'でタスクを作成する必要はありません。また、タスクタイプのオブジェクトを宣言することもできます。 –

答えて

5

は、通常は、 accept文を含むタスクへ/から渡された引数をコピーするに accept文を制限しますしたがって、ループ全体が完了してから P_EXECUTE_ENTRYが次のタスクに進むことができます。 - 終了するほとんどのプログラムは気にしないだろう、オペレーティングシステムのためにタスクを割り当て解除については

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; 

:、この問題を解決するタスク変数にループ回数を保存してaccept外ループを実行するために

プロセス終了時にメモリーを解放します。この場合、タスクが実際に終了する前に、割り当てを解除することはほとんどありません。実行中のタスクの割り当てを解除すると、予期しない動作が発生する可能性があります。これをどうやって管理するかは、別の質問になるはずです。

3

タスクはランデブー時に同期されます(つまり、acceptステートメント内にある限り)。あなたは

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; 

呼び出し側がend P_ITERATEまでブロックされていると言うとき

accept Start (Steps : in Positive) do 
    Count := Steps; 
end Start; 

for I in 1 .. Count loop 
    ...