线程'std::system_error' what() 操作不允许



我的代码中有一个线程异常。基本上,这是一个生产者-消费者问题,不同之处在于,消费者在从主队列消费之前,必须先清空自己的队列,再加上根据值,他们将数字添加到另一个消费者队列或进行处理。

代码按照预期工作,但在随机运行一段时间后会抛出以下错误:

terminate called after throwing an instance of 'std::system_error' what(): Operation not permitted

我的想法用完了,有时它处理6个值,其他600个。

提前感谢!

#include <iostream>
#include <thread>
#include <mutex>
#include <fstream>
#include <queue>
#include <cstdlib>
#include <condition_variable>
using namespace std;
queue<int> main_queue;
queue<int> baker_queue;
queue<int> groceries_queue;
mutex mutex1;

void clients_arrival(){
int random;
int random_2;
int i=0;
srand((unsigned)time(NULL));
while(true){
unique_lock<mutex> locker(mutex1);
random = 1+(rand()%3);
random_2 = 100+(rand()%1200);
main_queue.push(random);cout << "arrives client number "<<i+1<<" and has value "<<main_queue.back() << endl;
locker.unlock();
std::this_thread::sleep_for(chrono::milliseconds(random_2));
i++;
}
}

void baker_reception() {
while (true) {
unique_lock<mutex> locker(mutex1);
if (!main_queue.empty()) {
if (baker_queue.empty()) {
int a = main_queue.front();
main_queue.pop();
baker_queue.push(a);
cout << "baker empty, it removed an " << baker_queue.front() << endl;
if (a == 2) {
int b = a;
groceries_queue.push(b);
baker_queue.pop();
}
if (a == 3) {
int b = 2;
groceries_queue.push(b);
baker_queue.pop();
}
if (a == 1) {
baker_queue.pop();
}
locker.unlock();
std::this_thread::sleep_for(chrono::milliseconds(400));
}
if (!baker_queue.empty()) {
cout << "baker not empty, removed an " << baker_queue.front() << endl;
int a = baker_queue.front();
if (a == 2) {
int b = a;
groceries_queue.push(b);
baker_queue.pop();
}
if (a == 3) {
int b = 2;
groceries_queue.push(b);
baker_queue.pop();
}
if (a == 1) {
baker_queue.pop();
}
locker.unlock();
std::this_thread::sleep_for(chrono::milliseconds(400));
}
}
else {
locker.unlock();
std::this_thread::sleep_for(chrono::milliseconds(400));
}
}
}void groceries_reception() {
while (true) {
unique_lock<mutex> locker(mutex1);
if(!main_queue.empty()){
if (groceries_queue.empty()) {
int a = main_queue.front();
main_queue.pop();
groceries_queue.push(a);
cout << "Groceries empty, it removed an " << groceries_queue.front() << endl;
if (a == 1) {
int b = a;
baker_queue.push(b);
groceries_queue.pop();
}
if (a == 3) {
int b = 1;
baker_queue.push(b);
groceries_queue.pop();
}
if (a == 2) {
groceries_queue.pop();
}
locker.unlock();
std::this_thread::sleep_for(chrono::milliseconds(400));
}
if (!groceries_queue.empty()) {
cout << "Groceries not empty, removed an " << groceries_queue.front() << endl;
int a = groceries_queue.front();
if (a == 1) {
baker_queue.push(a);
groceries_queue.pop();
}
if (a == 3) {
int b = 1;
baker_queue.push(b);
groceries_queue.pop();
}
if (a == 2) {
groceries_queue.pop();
}
locker.unlock();
std::this_thread::sleep_for(chrono::milliseconds(400));
}
}
else {
locker.unlock();
std::this_thread::sleep_for(chrono::milliseconds(400));
}
}
}


int main() {
std::thread client(clients_arrival);
std::thread groceries(groceries_reception);
std::thread baker(baker_reception);
client.join();
baker.join();
groceries.join();
}

std::system_errorstd::thread构造函数或unlocks之一抛出。

既然你说程序正确地启动了线程,那么后者就是问题所在。如果没有关联的互斥对象或互斥对象未锁定,则unlock抛出std::system_error

因此,在您的情况下,您正试图解锁未锁定的互斥体,例如,因为您之前已经解锁了它。

看看groceries_reception。如果您使用第一个if (groceries_queue.empty())分支,那么您将在睡眠之前解锁互斥锁。睡眠后,您继续执行,将测试下一个if,即if (!groceries_queue.empty())。因为其他线程可能已经在其间修改了groceries_queue,所以现在也可以采用此分支。但在这个分支中,您再次调用locker.unlock()。这就是抛出异常的地方,因为您实际上不再持有锁。

在其他函数中也存在同样的问题。如果只想执行其中一个分支,请使用else if

然而,让锁通过作用域端的析构函数解锁会更干净。如果你想在解锁后睡觉,只需在锁的范围外制作一个人工范围:

{
unique_lock<mutex> locker(mutex1);
// do something with lock, don't call unlock
}
std::this_thread::sleep_for(chrono::milliseconds(400));

或者,如果在第一次循环迭代开始时情况良好,您可以在锁定之前先休眠:

std::this_thread::sleep_for(chrono::milliseconds(400));
unique_lock<mutex> locker(mutex1);
// do something with lock, don't call unlock

最新更新