簡體   English   中英

條件變量+互斥鎖+pthreads的C++生產者消費者問題

[英]C++ Producer Consumer Problem with condition variable + mutex + pthreads

我需要用c++做生產者消費者問題,解決1個消費者和6個生產者,以及1個生產者和6個消費者,下面是問題的陳述。

問題 1:想象一下,你正在一家非常繁忙的餐廳等一些朋友,你正在看着服務員,他們在餐桌上侍候,把食物從廚房帶到他們的餐桌上。 這是經典的“生產者-消費者”問題的一個例子。服務器有限制,廚房不斷生產食物。考慮到服務器(消費者)有限制和“無限”供應的食物由廚師(制作人)制作。

一種促進識別並因此減少為“生產者-消費者”問題的方法是限制消費者的數量,從而限制膳食的無限數量。 在廚房生產。 因此,建議存在交通燈來控制服務員將采取的膳食的生產順序。

該程序將類似於:

  1. 創建一個信號量;
  2. 創建服務器和廚師線程;
  3. 制作盡可能多的飯菜,並記錄排隊的飯菜數量;
  4. 服務器線程將一直運行,直到它設法提供表中生產的所有餐點;
  5. 線程必須與主線程“連接”。

還要考慮有 6 名廚師和 1 名服務員。 如果您願意,您可以考慮廚師制作一頓飯需要 50 微秒,而服務器需要 10 微秒才能將飯菜送上餐桌。 設置要服務的最大客戶數。 在執行結束時,在屏幕上打印哪個廚師最閑,哪個廚師最空閑,以及每位廚師制作了多少餐。

問題 2:考慮上述餐廳。 現在考慮有 1 個廚師和 6 個服務員。 假設廚師需要 50 微秒來制作一頓飯,而服務器需要 15 微秒將飯菜送到餐桌上。 設置要服務的最大客戶數。 打印哪個服務器空閑最多和最少,以及每個服務器提供了多少餐點。

我設法解決了 6 個生產者和 1 個消費者,但是對於 6 個消費者和 1 個生產者它不起作用,似乎程序陷入了一些死鎖。 如果有人知道如何提供幫助,我將不勝感激。

#include <iostream>
#include <random>
#include <chrono>
#include <thread>
#include <mutex>
#include <deque>

//The mutex class is a synchronization primitive that can be used to protect shared data
//from being simultaneously accessed by multiple threads.
std::mutex semaforo;                       //semafoto para fazer o controle de acesso do buffer
std::condition_variable notifica;          //variavel condicional para fazer a notificação de prato consumido/consumido
std::deque<int> buffer;                    //buffer de inteiros
const unsigned int capacidade_buffer = 10; //tamanho do buffer
const unsigned int numero_pratos = 25;     //numeros de pratos a serem produzidos

void produtor()
{
    unsigned static int contador_pratos_produzidos = 0;
    while (contador_pratos_produzidos < numero_pratos)
    {
        std::unique_lock<std::mutex> locker(semaforo);
        notifica.wait(locker, []
                      { return buffer.size() < capacidade_buffer; });
        std::this_thread::sleep_for(std::chrono::microseconds(50));
        buffer.push_back(contador_pratos_produzidos);
        if (contador_pratos_produzidos < numero_pratos)
        {
            contador_pratos_produzidos++;
        }
        locker.unlock();
        notifica.notify_all();
    }
}

void consumidor(int ID, std::vector<int> &consumido)
{
    unsigned static int contador_pratos_consumidos = 0;
    while (contador_pratos_consumidos < numero_pratos)
    {
        std::unique_lock<std::mutex> locker(semaforo);
        notifica.wait(locker, []
                      { return buffer.size() > 0; });
        std::this_thread::sleep_for(std::chrono::microseconds(15));
        buffer.pop_front();
        if (contador_pratos_consumidos < numero_pratos)
        {
            contador_pratos_consumidos++;
            consumido[ID]++;
        }
        locker.unlock();
        notifica.notify_one();
    }
}

int main()
{
    //vetor para contagem do consumo de cada garcon
    std::vector<int> consumido(6, 0);

    //vetor de threads garcon(consumidores)
    std::vector<std::thread> consumidores;
    for (int k = 0; k < 6; k++)
    {
        consumidores.push_back(std::thread(consumidor, k, std::ref(consumido)));
    }

    //produtor/chef
    std::thread p1(produtor);

    for (auto &k : consumidores)
    {
        k.join();
    }
    p1.join();

    int mais_ocioso = 200, menos_ocioso = 0, mais, menos;
    for (int k = 0; k < 6; k++)
    {
        std::cout << "Garcon " << k + 1 << " entregou " << consumido[k] << " pratos\n";
        if (consumido[k] > menos_ocioso)
        {
            menos = k + 1;
            menos_ocioso = consumido[k];
        }
        if (consumido[k] < mais_ocioso)
        {
            mais = k + 1;
            mais_ocioso = consumido[k];
        }
    }
    std::cout << "\nO mais ocioso foi o garcon " << mais << " e o menos ocioso foi o garcon " << menos << "\n";
}

消費者和生產者函數中都存在相同的錯誤。 我將解釋其中一個,同樣的錯誤也必須在另一個中修復。

unsigned static int contador_pratos_consumidos = 0;
while (contador_pratos_consumidos < numero_pratos)
{

這個static計數器被多個執行線程訪問和修改。

多個執行線程使用的任何非原子對象都必須正確排序(僅在持有適當的互斥鎖時才能訪問)。

如果您將注意力集中在上述兩行上,很明顯該計數器是在沒有任何互斥鎖保護的情況下訪問的。 一旦你意識到這一點,錯誤numero_pratos明顯了:在某些時候contador_pratos_consumidos將比numero_pratos 當這種情況發生時,您可以有多個執行線程while評估while條件,並且所有線程都會很高興地得出結論,這是真的。

多個執行線程然后進入while循環。 一個人將成功獲取互斥鎖並消耗“產品”,然后完成。 剩余的執行線程將永遠等待另一個永遠不會到達的“產品”。 不會再生產更多的產品。 他們沒有湯。

同樣的錯誤也存在於生產者中,只是錯誤的影響會相當微妙:最終會生產出比應有的更多的產品。

當然,迂腐地說,所有這些都是未定義的行為,所以任何事情都可能發生,但這些是這種未定義行為的典型的、通常的后果。 必須修復這兩個錯誤才能使該算法正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM