我已经在
producerconsumer_sem.adb
中调用了Semaphore.adb
来使用此Semaphore。 我获得了以下输出。
我不确定信号量的初始化是否正确:
S: CountingSemaphore(1,1);
。我不知道何时调用
S.wait
和S.Signal
。 现在我随机在生产者将项目放入缓冲区X := I;
之前调用了S.wait
,在X := I;
后调用了S.Signal
。 这是正确的方法吗?
输出:生产者-消费者问题 程序
producerconsumer.adb
实现了生产者-消费者问题的不可靠实现,其中数据很可能会丢失。 在接下来的内容中,您将使用三种不同的通信机制来实现生产者-消费者问题的可靠实现。信号量
Ada语言没有直接提供用于信号量的库函数。但是,可以通过受保护对象实现信号量。 在文件Semaphores.ads中创建包规范Semaphore,并在文件
Semaphores.adb
中创建相应的包体,以实现计数信号量。 课程页面上提供了该软件包的骨架。使用信号量包进行生产者-消费者问题的可靠实现。 修改文件
producerconsumer.adb
,并将最终代码保存为producerconsumer_sem.adb
。 要使用信号量程序包,它应安装在与producerconsumer_sem.adb
相同的目录中。 然后可以通过以下方式访问它:
with Semaphores;
use Semaphores;
输出结果: 1 1 1 2 2 3 4 4 5 6 6 7 7 8 9 9 9 10 11 11 11 12 12 13 13 13 14 15 15 16 16 17 18 18 18 19 20 20 21 21 22 22 23 24 24 24 24 25 25 26 27 27 28 29 29 30 30 31 31 32 32 33 33 33 34 35 35 35 36 36 37 37 37 38 38 38 39 40 40 40
该套件
package Semaphores is
protected type CountingSemaphore(Max: Natural; Initial: Natural) is
entry Wait;
entry Signal;
private
Count : Natural := Initial;
MaxCount : Natural := Max;
end CountingSemaphore;
end Semaphores;
我实现了信号量
semaphores.adb
。package body Semaphores is
protected body CountingSemaphore is
entry Wait when Count > 0 is
begin
Count := Count - 1;
end Wait;
entry Signal when Count < MaxCount is
begin
Count := Count + 1;
end Signal;
end CountingSemaphore;
end Semaphores;
producerconsumer_sem.adb
模块
with Ada.Text_IO;
use Ada.Text_IO;
with Ada.Real_Time;
use Ada.Real_Time;
with Ada.Numerics.Discrete_Random;
with Semaphores;
use Semaphores;
procedure ProducerConsumer_sem is
X : Integer; -- Shared Variable
N : constant Integer := 40; -- Number of produced and comsumed variables
S: CountingSemaphore(1,1);
--S1: CountingSemaphore(1,1);
pragma Volatile(X); -- For a volatile object all reads and updates of
-- the object as a whole are performed directly
-- to memory (Ada Reference Manual, C.6)
--Random Delays
subtype Delay_Interval is Integer range 50..250;
package Random_Delay is new Ada.Numerics.Discrete_Random
(Delay_Interval);
use Random_Delay;
G : Generator;
task Producer;
task Consumer;
task body Producer is
Next : Time;
begin
Next := Clock;
for I in 1..N loop
-- Write to X
S.Wait;
X := I;
S.Signal;
--Next 'Release' in 50..250ms
Next := Next + Milliseconds(Random(G));
Put_Line(Integer'Image(X));
delay until Next;
end loop;
end;
task body Consumer is
Next : Time;
begin
Next := Clock;
for I in 1..N loop
-- Read from X
S.Wait;
Put_Line(Integer'Image(X));
S.Signal;
Next := Next + Milliseconds(Random(G));
delay until Next;
end loop;
end;
begin -- main task
null;
end ProducerConsumer_sem;