创造有价值的网站,福州网站建设好的公司,网站设计便宜,深圳成交型网站建设1. thread对象的析构问题
在 C 多线程标准库中#xff0c;创建 thread 对象后#xff0c;必须在对象析构前决定是 detach 还是 join。若在 thread 对象销毁时仍未做出决策#xff0c;程序将会终止。
然而#xff0c;在创建 thread 对象后、调用 join 前的代码中#xff…
1. thread对象的析构问题
在 C 多线程标准库中创建 thread 对象后必须在对象析构前决定是 detach 还是 join。若在 thread 对象销毁时仍未做出决策程序将会终止。
然而在创建 thread 对象后、调用 join 前的代码中若程序抛出异常就会跳过 join 的调用进而导致程序终止。
因此必须在异常捕获中也调用 join。
这无疑增加了编程的复杂性因为每个相关位置都需要在正常流程中写一次 join在异常捕获中再写一次。
下面的代码将演示这一情况
#include iostream
#include threadusing namespace std;void threadFunc()
{cout Hello from thread endl;
}int main()
{thread t(threadFunc);try{throw runtime_error(Something went wrong);}catch (...){t.join();throw;}t.join();
}
2. 一种简单的解决办法——RAII
一种简单的解决办法就是使用RAII思想编写一个类来绑定一个thread对象在类的析构函数中调用thread对象的join方法。
下面的代码展示了这一点
#include iostream
#include threadusing namespace std;class thread_guard
{
public:thread_guard(std::thread t) : t_(t) {}~thread_guard(){if (t_.joinable()){t_.join();}}thread_guard(const thread_guard) delete;thread_guard operator(const thread_guard) delete;
private:thread t_;
};void threadFunc()
{cout Thread function running... endl;
}int main()
{thread t(threadFunc);thread_guard g(t);return 0;
}
局部对象会自动被销毁在销毁时thread_guard类对象的析构函数会自动调用thread类对象的join方法从而保证thread不会异常终止。
但是这种方法太死板了只会调用join方法。
我们可能希望自己选择detach或者join也可能想要在thread对象销毁时做一些别的事情。
出于这种想法本文提出了一种可扩展的智能析构线程下面将对其进行介绍。
3. 可扩展的智能析构线程
首先对于thread对象析构时不同的处理这里使用了策略模式。通过提供不同的策略类就可以扩展出不同的析构行为。
同时目前实现的策略类没有自己的成员函数所以采用了单例模式来创建避免创建出大量相同的对象而造成内存浪费。
最后通过简单工厂模式来获取策略类。
下面展示一下具体的代码
#include iostream
#include threadusing namespace std;class thread_destroy_strategy
{
public:virtual void destroy(thread t)const 0;virtual ~thread_destroy_strategy() default;
};class join_strategy : public thread_destroy_strategy
{
public:static join_strategy* getInstance(){static join_strategy instance;return instance;}void destroy(thread t)const override{if (t.joinable()){t.join();cout Thread this_thread::get_id() joined endl;}}
};class detach_strategy : public thread_destroy_strategy
{
public:static detach_strategy* getInstance(){static detach_strategy instance;return instance;}void destroy(thread t)const override{if (t.joinable()){t.detach();cout Thread this_thread::get_id() detached endl;}}
};enum class EThreadStrategy
{JOIN,DETACH
};class strategyFactory
{
public:static thread_destroy_strategy* getStrategy(EThreadStrategy strategy){switch (strategy){case EThreadStrategy::JOIN:return join_strategy::getInstance();case EThreadStrategy::DETACH:return detach_strategy::getInstance();default:return nullptr;}}
};class auto_thread
{
public:templatetypename F, typename... Argsauto_thread(F f, Args... args) : t(forwardF(f), forwardArgs(args)...) {}~auto_thread(){thread_destroy_strategy* pStrategy strategyFactory::getStrategy(strategy);if (pStrategy){pStrategy-destroy(t);}}auto_thread(const auto_thread) delete;auto_thread operator(const auto_thread) delete;public:void setStrategy(EThreadStrategy strategy_){strategy strategy_;}
private:thread t;EThreadStrategy strategy EThreadStrategy::JOIN;
};void threadFunc()
{cout Hello from thread endl;
}int main()
{auto_thread t(threadFunc);t.setStrategy(EThreadStrategy::JOIN); // 默认就是JOIN策略, 也可以设置为DETACH策略
}
策略类在destroy时打印了一下线程id。
运行结果如下图所示 以上就是本文的全部内容