2016-12-14 48 views
0

classical producer-consumer problem中,當共享緩衝區已滿且使用者等待共享緩衝區爲空時,我們有生產者等待。我們有兩個posix線程,一個生產者和其他工作者,使用sem_wait和sem_post爲空信號量和完整信號量(兩個計數信號量)相互同步。因此,信號量實現生產者 - 消費者代碼看起來如下:具有異常處理功能以防止死鎖的C++ Producer-Consumer

procedure producer() { 
    while (true) { 
     item = produceItem(); 
     down(emptyCount); 
      down(buffer_mutex); 
       putItemIntoBuffer(item); 
      up(buffer_mutex); 
     up(fillCount); 
    } 
} 

procedure consumer() { 
    while (true) { 
     down(fillCount); 
      down(buffer_mutex); 
       item = removeItemFromBuffer(); 
      up(buffer_mutex); 
     up(emptyCount); 
     consumeItem(item); 
    } 
} 

。假定生產商()和消費者()在獨立併發線程運行,當produceItemconsumeItem面臨的一個運行時異常會發生什麼導致線程優雅地處理異常,這樣兩個線程才能優雅地出來? 哪裏可以試試catch來處理這種情況?

+0

什麼是你預料之外的本質是什麼?如果生產者未能寫入共享緩衝區,那麼生產者應該處理該異常,並且消費者不應該意識到該異常。如果消費者未能從共享緩衝區讀取消息,則消費者應該處理該異常,並且生產者不應該意識到該異常。 –

+0

@JimRogers consumeItem(item)和/或produceItem()可能面臨異常 –

+0

這是真的,但兩個線程之間唯一的接口是緩衝區。如果生產者遇到異常,則消費者將等待它從異常中恢復。同樣,如果消費者遇到異常,生產者將等待消費者從異常中恢復。如果擔心生產者或消費者無法從異常中恢復,那麼應該等待每個線程等待訪問緩衝區。 –

回答

0

我使用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.