我嘗試在C 中實作生產者消費者問題,但是我發現我的實作有一個問題,它會產生直到大小達到容量然后開始消費程序。我想知道我的實施有什么問題。
#include <iostream>
#include <mutex>
#include <thread>
#include <queue>
#include <chrono>
using namespace std;
std::mutex mtx;
condition_variable cv;
queue<int> q;
int n=2;
int produceData() {
int res=rand()%1000;
cout<<"produce data:"<<res<<endl;
return res;
}
void consumeData() {
cout<<"consume data:"<<q.front()<<endl;
}
void producer(){
while(true) {
unique_lock<mutex> lk(mtx);
cv.wait(lk,[&](){return q.size()<n;});
q.push(produceData());
cv.notify_one();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void consumer() {
while(true) {
unique_lock<mutex> lk(mtx);
cv.wait(lk,[&](){return q.size()>0;});
consumeData();
q.pop();
cv.notify_one();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
int main() {
std::thread t1(producer);
std::thread t2(consumer);
t1.join();
t2.join();
return 0;
}
uj5u.com熱心網友回復:
您需要在睡眠時解鎖互斥鎖。只需引入一個新塊(花括號)即可。這樣unique_lock解構式將在睡眠呼叫之前運行。您也可以lk.unlock在 sleep 呼叫之前手動呼叫。而不是這個:
void producer(){
while(true) {
unique_lock<mutex> lk(mtx);
cv.wait(lk,[&](){return q.size()<n;});
q.push(produceData());
cv.notify_one();
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
這個:
void producer(){
while(true) {
{
unique_lock<mutex> lk(mtx);
cv.wait(lk,[&](){return q.size()<n;});
q.push(produceData());
cv.notify_one();
} // mutex will implicitly unlock on this line as a result of the destructor for lk
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
對消費者函式也進行類似的更改。
uj5u.com熱心網友回復:
添加到@selbie所說的,
你的執行緒正在互相挨餓。
大多數編程語言或庫中的大多數類似互斥鎖的東西都是不公平的。當一個執行緒釋放鎖而其他執行緒正在等待它時,鎖不會自動授予等待時間最長的執行緒。
在您的生產者和消費者回圈中,一旦任一執行緒釋放鎖,它所做的下一件事就是嘗試再次重新鎖定它。同時,另一個執行緒被阻塞——被換出——等待鎖。當一個執行緒釋放鎖時,作業系統將啟動喚醒另一個執行緒的程序,但在此之前很久,第一個執行緒再次獲取鎖。
正如@selbie 建議的sleep_for()那樣,將關鍵部分移出關鍵部分,可以讓其他執行緒有時間喚醒并為自己獲取鎖。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/520372.html
標籤:C 多线程
