与对象的互斥
mutexes with objects
我正在努力了解如何在c++中对对象使用互斥。我使用以下(琐碎的)多线程代码作为速度测试:
struct Rope{
int n, steps, offset;
//std::mutex mut;
Rope() {}
Rope(int n, int steps, int offset) : n(n), steps(steps), offset(offset) {}
void compute(){
double a[n];
for (int i=0; i<n; i++)
a[i] = i + offset;
for (int step=0; step<steps; step++)
for (int i=0; i<n; i++)
a[i] = sin(a[i]);
}
};
void runTest(){
int numRuns = 30;
int n = 10000;
int steps = 10000;
std::vector<Rope> ropes;
std::vector<std::thread> threads;
for (int i=0; i<numRuns; i++)
ropes.push_back(Rope(n, steps, i));
for (auto& r : ropes)
threads.push_back(std::thread(&Rope::compute, r));
for (std::thread& t : threads)
t.join();
}
代码运行得很好,在我的4核机器上速度提高了约4倍。当然,我没有在Rope中存储任何内容,所以不需要互斥。如果我现在认为我确实有一些需要保护的数据,我想在Rope上附加一个互斥对象,并(例如)在compute()循环中调用std::lock_guard。然而,如果我取消对互斥对象的注释,我会得到一堆关于赋值和复制运算符"使用已删除函数"的编译器错误。在安全锁定对象的目标中,我缺少什么?
使类线程安全的直接方法是添加互斥属性并将互斥锁定在访问器方法中
class cMyClass {
boost::mutex myMutex;
cSomeClass A;
public:
cSomeClass getA() {
boost::mutex::scoped_lock lock( myMutex );
return A;
}
};
问题是,这使得类不可复制。这一点很重要,尤其是当您想将类的对象存储在容器中时。
我可以通过将互斥对象设为静态对象来使事情正常工作。
class cMyClass {
static boost::mutex myMutex;
cSomeClass A;
public:
cSomeClass getA() {
boost::mutex::scoped_lock lock( myMutex );
return A;
}
};
然而,这意味着当访问任何其他实例时,类的每个实例都会阻塞,因为它们都共享相同的互斥对象。
从理论上讲,一个包含非静态互斥的类可以通过手工编码复制构造函数和赋值运算符来实现可复制性,从而省去互斥。然而,这很难做到,也很乏味,尤其是对于一个具有大量属性的类,这些属性在开发过程中经常发生变化。
如果一个静态互斥体在被阻止时阻止对类的所有实例的访问是不可接受的,那么最好和最简单的方法就是在类之外维护互斥体。以这种方式公开类的内部工作似乎很不幸,但替代方案要复杂得多,因此不可靠,而且当在访问类的代码级别处理互斥对象时,我经常发现有重要的优化。
您忽略了mutex
不可复制这一事实。这意味着什么复制互斥对象?获取和释放互斥的位置处于Rope::compute
中,并且由于所有线程都必须访问相同的互斥,您必须在runTest
中定义它,并通过引用或通过指针。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 提升 ASIO 无法识别计时器对象
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 如何返回一个类的两个对象相加的结果
- 使用std::函数映射对象方法
- 是否需要删除包含对象的"pair"?
- 如何在自删除后将对象设置为nullptr
- 迭代时从向量和内存中删除对象
- 构造对象的歧义
- 使用"std::unordereded_map"映射到"std::list"对象