w12*_*128 4 c++ multithreading thread-safety copy-constructor
当一个类拥有线程和互斥对象时,是否存在任何潜在的危险情况,其中复制/赋值将是危险的,这意味着应该删除复制构造函数和赋值?
考虑以下示例代码:
class A : B
{
std::thread t;
std::mutex m;
public:
A() : B() {}
virtual ~A()
{
if (t.joinable())
t.join();
}
// Should I delete cctor and assignment operator?
virtual void Method()
{
t = std::thread([this]
{
std::lock_guard<std::mutex> lck(m);
... // processing
});
}
// Other methods that lock on mutex m
};
Run Code Online (Sandbox Code Playgroud)
如果我理解正确,创建的线程Method()将不会在外部可见A,这意味着使用默认cctor进行复制不应该有问题,因为整个状态将被复制.我的推理是否正确?
任何其(扩展)状态包含指针的类必须具有已删除的副本/移动或必须编组该状态.
t = std::thread([this]
Run Code Online (Sandbox Code Playgroud)
上面的行存储指向this类的扩展状态的指针.
因此,默认复制和移动是不合适的.删除是一个选项; 仔细地,可能昂贵地编组另一个.
此外,线程和互斥体都只是移动类型.因此将隐式删除副本.
但是,您的移动分配/构造将由编译器编写并且错误.所以删除它们或修复它们.
没有类值类型(如Java/C#)的语言有一个成语,它有一个带状态的类和一个处理状态的线程.这是一个像C++这样以价值为中心的语言的糟糕计划.将您的状态存储在外部(比如,共享或唯一的ptr),与您的线程共享(作为共享ptr或观察ptr),突然默认移动是有意义的.
如果不这样做,你的对象变得无序 - 无法安全移动 - 这会削弱许多优秀的C++习语,或者迫使外部智能指针包装.
| 归档时间: |
|
| 查看次数: |
679 次 |
| 最近记录: |