C 生产者消费者具有例外处理以防止死锁
C++ Producer-Consumer with exception handling to prevent deadlock
在经典生产者 - 消费者问题中,我们让生产者在共享缓冲区满足时等待,而当共享缓冲区为空时,消费者等待。我们有两个POSIX线程,一个生产者和另一个工人,使用SEM_WAIT和SEM_POST彼此同步,用于空信号量和全信号量(都计数信号量)。因此,生产者 - 消费者代码的信号量实现如下:
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);
}
}
假定producter()和消费者()正在以独立并发线程运行,当produceItem
或consumeItem
面对运行时异常时会发生什么,导致线程优雅地处理异常,以便两个线程都可以优雅地出现?在哪里可以将尝试键入良好处理状况?
我使用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受保护的对象,例如上面示例中的缓冲区,提供了自动相互排除。在上面的示例中,缓冲区对象有两个条目,请放置。仅当缓冲区内部变量IS_NEW为false时,才能执行PUT条目。仅当缓冲区内部变量IS_NEW为TRUE时,才能执行GET条目。
生产者任务(类似于C 中的线程)包含一个外循环,将变量"值"设置为第一个1,然后是2个,最多为15。内部循环试图将值放在缓冲区中最高wait_limit时间。每次制作人将计时器设置为一秒钟,然后如果不成功,则再次尝试。如果制作人失败了Wait_limit Times,则会写入错误消息并终止。
消费者行为与生产者相似。它通过调用GET条目从缓冲区读取值。它也会等待每次尝试一半,然后在wait_limit连续读取从缓冲区读取值的失败后终止。
该程序的输出是:
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.
相关文章:
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何在没有死锁和/或争用的情况下正确使用 std::mutex C++?
- 用C++中的std::condition_variable将线程置于死锁中会有风险吗
- 使用 std::async 时死锁,将来作为成员
- 如何调试读写器锁的死锁?
- 为什么在Visual Studio 2013上的std::this_thread::sleep_for上死锁
- localtime() 函数正在调用 ___lll_lock_wait_private(),这会使线程陷入死锁
- 如何重现 Boost 进程文档提示的死锁?
- 多线程Windows GUI应用程序中的死锁
- 为什么printf会导致与future.get的死锁,而cout则不会?
- C++中具有阻塞队列和障碍的死锁
- 死锁使用 std::mutex 来保护多个线程中的 cout
- 避免并发等待对象中的死锁
- 在VC++中从DLLMAIN内部调用D3D的CREATEDEVICE时,它会创建一个死锁(loaderlock?)。有没有办法克服这个问题?最终目标内
- 当用2个螺纹锁定时,将recursive_mutex死锁
- 程序在 C++11 中使用条件变量进入死锁
- 一个线程提升的死锁
- 单个生产者/多个消费者死锁
- 当被调用方法使用调用方已锁定的同一锁时,如何避免死锁
- C 生产者消费者具有例外处理以防止死锁