我有一个类似main.cpp
的程序
#include <stdio.h>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread.hpp>
class MutexClass
{
private:
/* data */
boost::shared_mutex m_mutex;
bool running; //The flag program should stop
public:
MutexClass(/* args */);
~MutexClass();
void doSomeThing();
};
MutexClass::MutexClass(/* args */)
{
running = true;
printf("MutexClass()n");
}
MutexClass::~MutexClass()
{
printf("~MutexClassn");
boost::unique_lock<boost::shared_mutex> lock(m_mutex);
running = false;
}
void MutexClass::doSomeThing() {
printf("doSomeThingn"); //In fact, here is a callback or loop
boost::shared_lock<boost::shared_mutex> lock(m_mutex); //(1)Exception here
if(running){
printf("still running!n");
}
}
void doSomeThing(MutexClass* mtx) {
sleep(3);
mtx->doSomeThing();
}
void destroy(MutexClass* mtx) {
sleep(2);
delete mtx;
mtx = NULL;
}
int main(int argc, char* argv[])
{
MutexClass* mtx = new MutexClass();
boost::thread thrd1(&doSomeThing,mtx);
boost::thread thrd2(&destroy,mtx);
thrd1.join();
thrd2.join();
sleep(5);
return 0;
}
当我用运行此文件时
g++main.cpp-lbox_system-lbox_thread-g-o main&/主
它显示
MutexClass()
~MutexClass
doSomeThing
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::lock_error> >'
what(): boost: mutex lock failed in pthread_mutex_lock: Invalid argument
Aborted
我知道它在第33行崩溃了,这是函数中的注释行
void MutexClass::doSomeThing() {
printf("doSomeThingn"); //In fact, here is a callback or loop
boost::shared_lock<boost::shared_mutex> lock(m_mutex); //Exception here
if(running){
printf("still running!n");
}
}
环境:增强版本为1.54
我的问题是:程序是multiple-read/single-write
,如果MutexClass已经运行析构函数,在其他线程中运行doSomeThing时,我如何避免这种情况
并且只能添加try/catch块
谢谢!
有很多方法可以实现。这里的主要目标是不要delete
您的对象,直到所有使用它的例程都失效为止。其中一种方法是使用shared_ptr
将对象传递到线程中。
看看我在这里做了什么来使代码工作。我已经用评论了重大变化!!!
#include <stdio.h>
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread.hpp>
#include <thread>
class MutexClass
{
private:
/* data */
boost::shared_mutex m_mutex;
bool running; //The flag program should stop
public:
MutexClass(/* args */);
~MutexClass();
void doSomeThing();
void stop() { // !!! changing running to false moves to this method
printf("stop()n");
boost::unique_lock<boost::shared_mutex> lock(m_mutex);
running = false;
}
};
MutexClass::MutexClass(/* args */)
{
running = true;
printf("MutexClass()n");
}
MutexClass::~MutexClass()
{
printf("~MutexClassn");
}
void MutexClass::doSomeThing() {
printf("doSomeThingn"); //In fact, here is a callback or loop
boost::shared_lock<boost::shared_mutex> lock(m_mutex); //(1)Exception here
if (running) {
printf("still running!n");
}
else {
printf("not running!n");
}
}
void doSomeThing(std::shared_ptr<MutexClass> mtx) {
std::this_thread::sleep_for(std::chrono::seconds(3));
mtx->doSomeThing();
}
void destroy(std::shared_ptr<MutexClass> mtx) {
std::this_thread::sleep_for(std::chrono::seconds(2));
mtx->stop(); // !!! Stop instead of delete
}
int main(int argc, char* argv[])
{
auto mtx = std::make_shared<MutexClass>(); // !!! store mtx in shared ptr
boost::thread thrd1(&doSomeThing, mtx);
boost::thread thrd2(&destroy, std::move(mtx)); // !!! You can play with std::move here to see where your object is destroyed.
thrd1.join();
thrd2.join();
printf("after joinn"); // before this line mtx object should be destroyed
std::this_thread::sleep_for(std::chrono::seconds(5));
//sleep(5);
return 0;
}