多个生产者/消费者和临界区代码问题

发布于 2024-08-04 00:17:57 字数 1185 浏览 6 评论 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

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

I am attempting a multiple producer/consumer problem in C, but its not working as expected. The following is some pseudo code to represent my implementation.

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);
}

However, with this solution data1 will fill up, but thread2 will lock and never run. Is there something wrong with my implementation?

EDIT #1

One of the problems I found was that my second mutex was not being created correctly. I don't know what's wrong with it so I'm just using the first mutex for all threads. There is also something else I have done to get it working, so I'll update my pseudo-code to reflect this later when I have a minute.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

傾旎 2024-08-11 00:17:57

如果您对 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
}

If you use some sort of queuing type for Data, you should be able to remove the "empty" semaphores completely, unless you're trying to impose the condition that each Data queue depth is strictly 0 or 1. If you use a local variable in thread2, you can reduce the size of the critical section.

The code then becomes something like this:

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
}
忆伤 2024-08-11 00:17:57

确保您最初发布 data1_emptydata2_empty

Make sure you post data1_empty and data2_empty initially.

第几種人 2024-08-11 00:17:57

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

What wrang-wrang said, and try not to hold the lock for data_1 while you're waiting for data_2_empty. You could achieve this by keeping an alternate buffer for data_1 and data_2 that you swap out. Thread_2 swaps data_1 while processing it into data_2, thread_3 swaps out data_2 while processing it. Your current pseudo-code will allow thread 1 and thread 3 to run concurrently, but it won't allow thread 2 to execute at the same time as either of the others.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文