c-如果有1个生产者和多个消费者缓冲区大小为1,生产者-消费者问题将如何解决



如果有一个生产者提供文件名,而有两个消费者使用文件名,那么生产者-消费者问题将如何解决。

问题是,添加文件名的缓冲区大小为1,这意味着我们不能有两个副本供每个消费者使用

对于同一个文件,两个使用者都有不同的逻辑来运行。

我还没有包含退出条件逻辑,但当文件名等于exit时,它将终止线程。

生产者/消费者之间通过指针共享数据

共享数据:

char* filenameBuffer;
pthread_mutex_t filenameMutex;
pthread_cond_t canProduceFilename;
pthread_cond_t canConsumeFilename;

目前我让制片人做这样的事情。

父/生产者线程-将循环直到我想退出

while(!exit)
{
pthread_mutex_lock(filenameMutex);
//Check if the string is empty.
if(filenameBuffer != '')
{
p_thread_cond_wait(canProduceFilename, filenameMutex);
}
scanf("%s", filenameBuffer);
pthread_cond_signal(canConsumeFilename);
pthread_mutex_unlock(filenameMutex);
}

儿童/消费者线程-我们有2个

while (!exit)
{
pthread_mutex_lock(filenameMutex);
//Loop until a string is produced.
while (filenameBuffer == '')
{
p_thread_cond_wait(canConsumeFilename, filenameMutex);
}
//Do something with filename, not relevant for solution.
pthread_mutex_unlock(filenameMutex);
}

那么,如果不控制每个使用者线程的顺序,我如何能够在使用者中使用文件名呢。我不想强迫哪个消费者可以先运行,因为这会破坏多线程的点。

如果需要任何澄清或更多信息,我会留下来。

任何讨论或指导都将不胜感激。

致以亲切的问候。

我已经制作了一个使用Ada编程语言实现这一功能的示例。由于文件名的处理对这个问题并不重要,我创建了两个消费者,他们处理他们接收到的任何字符串,直到字符串等于"0";退出";。

此示例创建一个受保护的对象,该对象包含一个元素缓冲区和一个计数器。它还实现了两个条目,写和读。写入条目仅在计数器等于0时执行。读取条目仅在计数器大于0时执行。

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
procedure Main is
type Count_Type is range 0..2;
protected buffer is
entry write(S : in Unbounded_String);
entry read(S : out Unbounded_String);
private
Counter : Count_Type := 0;
Element : Unbounded_String;
end Buffer;

protected body buffer is
entry write (S : in Unbounded_String) when Counter = 0 is
begin
Element := S;
Counter := 2;
end write;

entry read (S : out Unbounded_String) when Counter > 0 is
begin
S := Element;
Counter := Counter - 1;
end read;
end buffer;

task producer;

task body producer is
Msg : Unbounded_String := To_Unbounded_String("Message");
begin
for I in 0..9 loop
Msg := Msg & Integer'Image(I);
Buffer.write(Msg);
end loop;
Msg := To_Unbounded_String("Exit");
Buffer.Write(Msg);
end producer;

task consumer_1;

task body consumer_1 is
Msg : Unbounded_String;
begin
loop
Buffer.Read(Msg);
exit when To_String(Msg) = "Exit";
Put_Line("Con1 -> " & To_String(Msg));
end loop;
end consumer_1;

task consumer_2;

task body consumer_2 is
Msg : Unbounded_String;
begin
loop
Buffer.Read(Msg);
exit when To_String(Msg) = "Exit";
Put_Line("Con2 -> " & To_String(Msg));
end loop;
end consumer_2;
begin
null;
end Main;

程序的输出为:

Con1 -> Message 0
Con2 -> Message 0
Con1 -> Message 0 1
Con2 -> Message 0 1
Con1 -> Message 0 1 2
Con2 -> Message 0 1 2
Con2 -> Message 0 1 2 3
Con2 -> Message 0 1 2 3 4
Con1 -> Message 0 1 2 3
Con2 -> Message 0 1 2 3 4
Con1 -> Message 0 1 2 3 4 5
Con2 -> Message 0 1 2 3 4 5
Con1 -> Message 0 1 2 3 4 5 6
Con2 -> Message 0 1 2 3 4 5 6
Con1 -> Message 0 1 2 3 4 5 6 7
Con2 -> Message 0 1 2 3 4 5 6 7
Con1 -> Message 0 1 2 3 4 5 6 7 8
Con2 -> Message 0 1 2 3 4 5 6 7 8
Con1 -> Message 0 1 2 3 4 5 6 7 8 9
Con2 -> Message 0 1 2 3 4 5 6 7 8 9

最新更新