![](/img/trans.png)
[英]Pthreads - Producer and consumer with condition variable and mutex - join error and strange cout
[英]C++ Producer Consumer Problem with condition variable + mutex + pthreads
我需要用c++做生產者消費者問題,解決1個消費者和6個生產者,以及1個生產者和6個消費者,下面是問題的陳述。
問題 1:想象一下,你正在一家非常繁忙的餐廳等一些朋友,你正在看着服務員,他們在餐桌上侍候,把食物從廚房帶到他們的餐桌上。 這是經典的“生產者-消費者”問題的一個例子。服務器有限制,廚房不斷生產食物。考慮到服務器(消費者)有限制和“無限”供應的食物由廚師(制作人)制作。
一種促進識別並因此減少為“生產者-消費者”問題的方法是限制消費者的數量,從而限制膳食的無限數量。 在廚房生產。 因此,建議存在交通燈來控制服務員將采取的膳食的生產順序。
該程序將類似於:
還要考慮有 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.