0

我正在尝试 C 中的多生产者/消费者问题,但它没有按预期工作。以下是一些代表我的实现的伪代码。

Thread thread1;
Thread thread2;
Thread thread3;

Data data1;
Mutex data1_mutex;
Semaphore data1_empty;
Semaphore data1_fill;

Data data2;
Mutex data2_mutex;
Semaphore data2_empty;
Semaphore data2_fill;

thread1()
{
   // creates data and places it into data1.

   wait(data1_empty);
   lock(data1_mutex);

   // critical section

   unlock(data1_mutex);
   post(data1_fill);
}

thread2()
{
   // Removes data from data1, processes it, and places it into data2.

   // data1
   wait(data1_fill);
   lock(data1_mutex);

   // data2
   wait(data2_empty);
   lock(data2_mutex);

   // critical section

   // data2
   unlock(data2_mutex);
   post(data2_fill);

   // data1
   unlock(data1_mutex);
   post(data1_empty);
}

thread3()
{
   // Removes data from data2, prints its results, and removes it.

   wait(data2_fill);
   lock(data2_mutex);

   // critical section

   unlock(data2_mutex);
   post(data2_empty);
}

但是,使用此解决方案,data1 将被填满,但 thread2 将锁定并且永远不会运行。我的实现有问题吗?

编辑#1

我发现的问题之一是我的第二个互斥锁没有正确创建。我不知道它有什么问题,所以我只是对所有线程使用第一个互斥锁。为了让它正常工作,我还做了一些其他的事情,所以稍后我会更新我的伪代码以反映这一点。

4

3 回答 3

1

如果您对 使用某种排队类型Data,则应该能够完全删除“空”信号量,除非您试图强加每个Data队列深度严格为 0 或 1 的条件。如果您在 中使用局部变量thread2,您可以减小临界区的大小。

然后代码变成这样:

thread1() {
    //Wait for data to put in the queue (i.e. a blocking socket read)
    lock(data1_mutex);
    data1.push(someData);
    unlock(data1_mutex);
    post(data1_fill);
}

thread2() {
    DataType dataElement;
    wait(data1_fill);
    lock(data1_mutex);
    dataElement = data1.pop();
    unlock(data1_mutex);

    lock(data2_mutex);
    data2.push(dataElement);
    unlock(data2_mutex);
    post(data2_fill);
}

thread3() {
    DataType dataElement;
    wait(data2_fill);
    lock(data2_mutex);
    dataElement = data2.pop();
    unlock(data2_mutex);
    //do something with dataElement here
}
于 2009-12-02T18:54:37.907 回答
0

确保您发布data1_emptydata2_empty 最初。

于 2009-09-10T23:15:41.443 回答
0

wrang-wrang 所说的,在等待 data_2_empty 时尽量不要持有 data_1 的锁。您可以通过为您换出的 data_1 和 data_2 保留备用缓冲区来实现此目的。Thread_2 在处理 data_1 时将其交换为 data_2,thread_3 在处理时将 ​​data_2 换出。您当前的伪代码将允许线程 1 和线程 3 同时运行,但它不允许线程 2 与其他任何一个同时执行。

于 2009-09-11T00:02:18.293 回答