Boost多线程异常

Boost multithreading exception

我有一个类似 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("~MutexClass\n");
    boost::unique_lock<boost::shared_mutex> lock(m_mutex);
    running = false;
}

void MutexClass::doSomeThing() {
    printf("doSomeThing\n");  //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 -lboost_system -lboost_thread -g -o main && ./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("doSomeThing\n");  //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");
    }    
}

环境:Boost 版本为 1.54

我的问题是:程序是multiple-read/single-write,如果MutexClass已经运行析构函数。
而且只能加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("~MutexClass\n");
}

void MutexClass::doSomeThing() {
    printf("doSomeThing\n");  //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 join\n");     // before this line mtx object should be destroyed
    std::this_thread::sleep_for(std::chrono::seconds(5));
    //sleep(5);
    return 0;
}