gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-28 01:27:03 24 4
gpt4 key购买 nike

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

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

在抛出“std::system_error”实例后调用终止
what(): 不允许操作

我的想法用完了,有时它处理 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 构造函数或 unlock 之一抛出。

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

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

查看 groceries_reception。如果您采用第一个 if (groceries_queue.empty()) 分支,您将在 sleep 前解锁互斥量。休眠后继续执行,下一个 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

关于c++ - 线程 'std::system_error' what() 操作不允许,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53282723/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com