当使用共享数据拥有多个线程时,如何在抛出异常时正确处理对该数据的破坏?
我正在开发一个应用程序,我希望一个进程在等待通过网络从另一个进程发送的结果时正在工作。我实现了一个创建线程来等待结果的类,如下所示(实际代码太大而无法在此处发布,所以这是一个小例子):
class Notifier {
public:
Notifier(Client* _client) : value(-1), client(_client) {
listener = boost::thread(&Notifer::Listen, this);
}
void Listen() {
try {
int rec = client->Receive(); //blocking call to receive data over a socket
boost::scoped_lock sl(mutex);
value = rec;
} catch (...) {
cout << "Exception thrown in listener" << endl;
}
}
int Get() {
boost::mutex::scoped_lock sl(mutex);
return value;
}
private:
int value;
boost::mutex;
boost::thread listener;
Client* client;
}
int main() {
Client client; //initialize client, connect, etc.
Notifier n(client);
while(n.Get() < 0) {
// do work
cout << "Waiting for data" << endl;
sleep(1);
}
}
这对我来说很好,直到我添加异常处理:
int main() {
try {
Client client; //initialize client, connect, etc.
Notifier n(client);
while(n.Get() < 0) {
// do work
cout << "Waiting for data" << endl;
sleep(1);
throw exception();
}
} catch(...) {
cout << "Exception thrown in main" << endl;
}
return 0;
}
我收到错误
“提升:pthread_mutex_lock中的互斥锁失败:参数无效”。
我的猜测是,当抛出异常时,main
函数的堆栈会被解除,从而破坏互斥锁。然后Receive()
函数中的Listen
调用返回,scoped_lock
构造函数尝试锁定不存在的互斥锁,从而导致错误。
有人可以确认这确实是发生了什么吗?如果是这样,有没有办法与线程通信互斥不再存在或者线程应该终止?或者是否有一种更加安全的方式来做我想做的事情?
答案 0 :(得分:0)
您必须为Notifier
类编写正确的析构函数,这将取消所有被阻止的调用(即取消阻塞client->Receive()
),然后终止listener
线程。您还需要修改Notifier::Listen()
以定期检查线程终止请求...然后一切都会正常。