我正在学习多线程,我想模拟生产者 - 消费者问题(如果我可以称之为信号量,则使用信号量)。
我有一个包含队列的类,生产者将整数推送到队列中,消费者检索并打印它。我模拟如下
class TestClass{
public:
void producer( int i ){
unique_lock<mutex> l(m);
q.push(i);
if( q.size() )
cnd.notify_all();
}
void consumer(){
unique_lock<mutex> l(m);
while( q.empty() ){
cnd.wait(l);
}
int tmp = q.front();
q.pop();
cout << "Producer got " << tmp << endl;
}
void ConsumerInit( int threads ){
for( int i = 0; i < threads; i++ ){
thrs[i] = thread(&TestClass::consumer, this );
}
for( auto &a : thrs )
a.join();
}
private:
queue<int> q;
vector<thread> thrs;
mutex m;
condition_variable cnd;
};
我使用了一个小控制台应用程序来调用数据:
int main(){
int x;
TestClass t;
int counter = 0;
while( cin >> x ){
if( x == 0 )
break;
if( x == 1)
t.producer(counter++);
if( x == 2 )
t.ConsumerInit(5);
}
}
因此,当用户输入 1 时,会将数据推送到队列中,如果用户按下 2,则会产生线程。
以任何调用它的顺序,例如,按 1 1 然后按 2,或 2 1 1 它会引发段错误。我不确定为什么我对代码的理解如下:让我们假设 order 2 1 1
我初始化了 5 个线程,他们看到队列是空的,所以他们去睡觉了。当我将一个数字推送到队列时,它会通知所有正在休眠的线程。第一个再次唤醒锁定互斥锁并继续从队列中检索数字然后释放互斥锁,当互斥锁被释放时,另一个线程执行相同操作并解锁互斥锁,互斥锁解锁后的第三个线程仍在循环中,看到队列再次为空并再次进入睡眠状态,与所有剩余线程相同。
这个逻辑正确吗?如果是这样,为什么这会一直抛出段错误,如果不是,我感谢所有解释。
谢谢您的帮助!
//edit 通过回答建议,我将 [] 替换为 vector.push_back ,但消费者现在对数据不做任何事情,不接受或打印它。