首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >生产者-消费者模型

生产者-消费者模型
EN

Stack Overflow用户
提问于 2020-04-28 10:42:15
回答 1查看 500关注 0票数 1

我试图模拟生产者-消费者的多线程模型。

我们假定有三条规则需要遵守:

当桶中满是products.

  • Consumer时,
  1. 生产者不能将产品添加到桶中,当桶为empty.
  2. Producing时,无法从桶中获取产品,并且不能同时进行消费。换句话说,这两个操作是异步的。

我现在拥有的是:

  1. a int varible用于将产品数量存储在存储桶

中的变量存储桶容量的const int变量,在我的代码中值为5。

  1. 是互斥量的int变量,初始值为1H 217H 118a vector<HANDLE>用于挂起句柄的函数调度。H 220G 221

的结果是:有时它工作得很好,但有时它会变成死锁。代码和结果如下:

代码:

代码语言:javascript
复制
#include <iostream>
#include <Windows.h>
#include <vector>

using namespace std;

// the count of product, the initial value is 0
int product_count = 0;

const int product_capacity = 5;

int mutex = 1;

vector<HANDLE> suspendedHandleVector;

HANDLE GetCurrentRealHandle() {
    HANDLE realHandle = 0;
    return OpenThread(THREAD_ALL_ACCESS, TRUE, GetCurrentThreadId());
}

void ThreadScheduling() {
    if (suspendedHandleVector.size() > 0) {
        HANDLE handle = suspendedHandleVector[0];
        suspendedHandleVector.erase(suspendedHandleVector.begin());
        ResumeThread(handle);
    }
}

void P() {
    --mutex;
    if (mutex < 0) {
        auto handle = GetCurrentRealHandle();
        suspendedHandleVector.push_back(handle);
        SuspendThread(handle);
    }
}

void V() {
    ++mutex;
    if (mutex >= 0) {
        ThreadScheduling();
    }
}

DWORD WINAPI ProducerThread(LPVOID param) {
    while (true) {
        P();
        if (product_count == product_capacity) {
            V();
            continue;
        }
        ++product_count;
        cout << "I'm producer, and there are " << product_count << " products now" << endl;
        V();
        Sleep(100);
    }
    return 0;
}

DWORD WINAPI ConsumerThread(LPVOID param) {
    while (true) {
        P();
        if (product_count == 0) {
            V();
            continue;
        }
        --product_count;
        cout << "I'm consumer, and there are " << product_count << " products rest now" << endl;
        V();
        Sleep(150);
    }
    return 0;
}

void main() {
    auto producer_handle = CreateThread(nullptr, 0, ProducerThread, nullptr, 0, nullptr);
    auto consumer_handle = CreateThread(nullptr, 0, ConsumerThread, nullptr, 0, nullptr);
    while (true) {
        cout << suspendedHandleVector.size() << endl; // This is for debugging
        Sleep(100);
    }
}

当结果按预期工作时,

代码语言:javascript
复制
0
I'm producer, and there are 1 products now
I'm consumer, and there are 0 products rest now
0
I'm producer, and there are 1 products now
I'm consumer, and there are 0 products rest now
0
I'm producer, and there are 1 products now
0
I'm consumer, and there are 0 products rest now
I'm producer, and there are 1 products now
0
I'm producer, and there are 2 products now
I'm consumer, and there are 1 products rest now

,这是一个期望的无限循环。产品计数将分别为4和5,因为我将生产者的睡眠时间设置为比消费者多一点时间。

,但以下是意想不到的结果:

代码语言:javascript
复制
I'm producer, and there are 5 products now
I'm consumer, and there are 4 products rest now
0
I'm consumer, and there are 4 products rest now
I'm producer, and there are 5 products now
0
0
I'm consumer, and there are 4 products rest now
I'm producer, and there are 5 products now
0
2
2
2
2
2
2

正如我们所看到的,挂起的线程向量的大小从0变为2,忽略了1.。

,这仅仅是一个巧合,两个线程同时被唤醒,然后是一个冲突?

我认为我的代码有问题,需要您的帮助.

在测试过程中,我也遇到了一个问题:如何获得线程,然后将其存储在向量中。

我不确定是否使用OpenThread来做到这一点。我的课程要求我使用系统调用,所以我没有包括thread头文件。

谢谢你的帮助!

EN

回答 1

Stack Overflow用户

发布于 2020-04-28 13:23:39

在生产者-消费者问题中,有三个参与者:生产者、消费者和用来存储产生的数据的缓冲区。生产者和消费者通常生活在一个或多个线程中(多生产者、单消费者、单生产者、多消费者)。

现在,这个模式被广泛使用,因为它是避免显式同步的方法之一。

正如我所说,消费者和消费者通常生活在一个或多个线程中。缓冲区通常是同步队列(既可以是锁定队列,也可以是无锁队列)。

非常短的片段:

代码语言:javascript
复制
SyncronizedQueue queue;

void consumer()
{
  while(1) {
    queue.push(std::rand());
  }
}

void producer()
{
    while(1)
    {
      auto product = queue.pop();   // blocks until there are elements in the 
    }
}

void main()
{
  std::thread producerThread{producer};
  std::thread consumerThread{consumer};

  producerThread.join();
  consumerThread.join();
}

因此,任务是编写队列,这样就可以安全地执行push元素,并在新元素被推送时解锁pop

一个简单的实现方法是使用条件变量,这样pop函数就会被阻塞,直到一个条件被触发,而push方法将一个元素添加到队列中并触发条件。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61478260

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档