我使用Ada進行大多數多線程處理。下面的Ada示例顯示瞭如何將超時應用於等待條件變量允許消費者處理非響應式生產者以及生產者處理非響應式消費者。
------------------------------------------------------------------
-- Producer-Consumer Package --
------------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;
procedure Protected_Producer_Consumer is
protected Buffer is
entry Put(Item : in Integer);
entry Get(Item : out Integer);
private
Value : Integer := Integer'First;
Is_New : Boolean := False;
end Buffer;
protected body Buffer is
entry Put(Item : in Integer) when not Is_New is
begin
Value := Item;
Is_New := True;
end Put;
entry Get(Item : out Integer) when Is_New is
begin
Item := Value;
Is_New := False;
end Get;
end Buffer;
task producer;
task body producer is
Wait_Limit : constant Natural := 5;
Written : Boolean := False;
begin
for value in 1..15 loop
Written := False;
for try in 1..Wait_Limit loop
Select
Buffer.Put(Value);
Written := True;
or
delay 0.5;
end select;
exit when Written;
end loop;
if not Written then
Put_Line("Producer terminating. Consumer not responding.");
exit;
end if;
end loop;
end producer;
task consumer;
task body consumer is
Wait_Limit : Natural := 5;
Value_Read : Boolean;
The_Value : Integer;
begin
Loop
Value_Read := False;
for try in 1..Wait_Limit loop
select
Buffer.Get(The_Value);
Value_Read := True;
Put_Line("Consumer read value: " & Integer'Image(The_Value));
or
delay 0.5;
end select;
exit when Value_Read;
end loop;
if not Value_Read then
Put_Line("Consumer terminating. Producer not responding.");
exit;
end if;
end loop;
end Consumer;
begin
null;
end Protected_Producer_Consumer;
Ada受保護的對象,如上例中的Buffer,提供了自動互斥功能。在上面的例子中,Buffer對象有兩個入口Put和Get。 Put條目只能在Buffer內部變量Is_New爲False時執行。 Get條目只能在Buffer內部變量Is_New爲True時執行。
Producer任務(類似於C++中的線程)包含一個外部循環,該變量將變量「value」設置爲第一個1,然後是第二個,依此類推直到15.內部循環嘗試將值放入緩衝到Wait_Limit時間。生產者每次設置一個計時器半秒鐘,然後再次嘗試,如果不成功。如果生產者的Wait_Limit失敗,它會寫入一條錯誤消息並終止。
消費者行爲與生產者類似。它通過調用Get條目從Buffer讀取值。它也會在每次嘗試中等待半秒,並在Wait_Limit連續失敗後終止以從Buffer讀取值。
這個程序的輸出是:
Consumer read value: 1
Consumer read value: 2
Consumer read value: 3
Consumer read value: 4
Consumer read value: 5
Consumer read value: 6
Consumer read value: 7
Consumer read value: 8
Consumer read value: 9
Consumer read value: 10
Consumer read value: 11
Consumer read value: 12
Consumer read value: 13
Consumer read value: 14
Consumer read value: 15
Consumer terminating. Producer not responding.
什麼是你預料之外的本質是什麼?如果生產者未能寫入共享緩衝區,那麼生產者應該處理該異常,並且消費者不應該意識到該異常。如果消費者未能從共享緩衝區讀取消息,則消費者應該處理該異常,並且生產者不應該意識到該異常。 –
@JimRogers consumeItem(item)和/或produceItem()可能面臨異常 –
這是真的,但兩個線程之間唯一的接口是緩衝區。如果生產者遇到異常,則消費者將等待它從異常中恢復。同樣,如果消費者遇到異常,生產者將等待消費者從異常中恢復。如果擔心生產者或消費者無法從異常中恢復,那麼應該等待每個線程等待訪問緩衝區。 –