继承std::thread时如何安全调用成员函数
Posted
技术标签:
【中文标题】继承std::thread时如何安全调用成员函数【英文标题】:How to invoke member function safely when inheriting std::thread 【发布时间】:2019-10-08 02:59:22 【问题描述】:我的代码如下:
class MyThread : public std::thread
int a_;
public:
MyThread(int a)
: std::thread(&MyThread::run, this),
a_(a)
void run()
// use a_
;
我想拥有自己的线程类,它拥有 std::thread 提供的所有方法,所以我让 MyThread 类继承 std::thread。 在 MyThread 的构造函数中,我将其成员函数传递给 std::thread。编译没问题,但我担心在 std::thread 的构造函数中调用 run() 和初始化 a_ 之间存在竞争条件。
有没有办法让它安全?
【问题讨论】:
which has all the methods that std::thread provides
您具体指的是哪些方法?您无需继承即可访问公共成员函数。访问受保护的成员函数和变量可能是一种情况,但我不知道。
@TrickorTreat,join() 或 get_id() 等方法。我不想通过组合和适配 std::thread 对象在 MyThread 中再次添加这些接口,所以我直接将 std::thread 子类化。
【参考方案1】:
不要那样做。 “Has-a”(组合)比“is-a”(继承)有很多优势。
class MyThread
std::thread _thread;
int _a;
public:
MyThread(int a) : _a(a)
_thread = std::thread([this] run(););
void run()
// thread code here
;
void join()
_thread.join();
;
更好的方法是认识到线程和该线程上的操作是两个不同的对象:
class WorkerOperation
int _a;
public:
WorkerOperation(int a) : _a(a)
void run()
// your code goes here
;
然后创建一个线程:
shared_ptr<WorkerOperation> spOp = make_shared<WorkerOperation>(42);
std::thread t = std::thread([spOp] spOp->run(););
如果你真的需要将操作和线程配对:
std::pair<WorkerOperation, std::thread> threadpair;
threadpair.first = spOp;
threadpair.second = std::move(t);
【讨论】:
【参考方案2】:要修复错误,您可以编写:
MyThread(int a)
:a_(a)
(std::thread&)(*this) = std::thread(&MyThread::run, this);
这样,线程以初始化的a_
运行。
一般来说,我认为从 std::thread 继承并不是一个好主意。最好将其设为私有成员并运行它。否则,如果您允许他们公开将您的课程转换为 std::thread& ,用户可能会做一些奇怪的事情。就像执行与您预期不同的功能一样。
【讨论】:
好吧,这可能是添加 MyThread& operator=(std::thread&&) 覆盖后的解决方法。谢谢@alx23z【参考方案3】:但我担心在 std::thread 的构造函数中调用 run() 和初始化 a_ 之间存在竞争条件。
是的,
您可以重新排序成员/基地:
struct MyThreadData
int _a;
;
struct MyThread : MyThreadData, std::thread
public:
explicit MyThread(int a) : MyThreadDataa, _thread([this] run();)
void run()
// thread code here
;
;
【讨论】:
以上是关于继承std::thread时如何安全调用成员函数的主要内容,如果未能解决你的问题,请参考以下文章
无法将类成员函数传递给另一个函数(std::thread::thread)